2012-09-20 2 views
3

안녕하세요 월드 코드 Gas, NASMYASM에 멀티 플랫폼 작업이 진행 중입니다. 해당 실행 파일을 76KB에서 기본 Hello World C 프로그램으로 간주되는 Hello World 어셈블리 프로그램에 더 적합한 것으로 축소하고 싶습니다. 80KB의 실행 파일로 이어지고 어셈블리는 훨씬 더 작아야합니다. 실행 파일의 대부분은 링커 옵션의 정크로 가득 차 있다고 생각합니다.어셈블러 실행 파일을 어떻게 잘라내나요?

추적 :

LIBS=c:/strawberry/c/i686-w64-mingw32/lib/crt2.o -Lc:/strawberry/c/i686-w64-mingw32/lib -lmingw32 -lmingwex -lmsvcrt 

ld ld -o $(EXECUTABLE) hello.o $(LIBS) 

hello.exe 
Hello World! 

코드 :

.data 

msg: .ascii "Hello World!\0" 

.text 

.global _main 

_main: 

pushl $msg 
call _puts 

leave 
movl $0, %eax 
ret 

나는, LIBS에있는 옵션 중 하나를 제거 링크 프로세스가 실패하거나 실행시 생성 된 실행 파일이 윈도우 오류가 발생하거나합니다. 따라서 논리적 인 작업은 puts 호출을 sys_write, 과 같은 간단한 것으로 바꾸는 것입니다. 그러나이 멀티 플랫폼을 수행하는 방법을 모르겠습니다.. 온라인에있는 작은 문서에서 int 0x80을 사용하여 커널 호출을 수행한다고 나와 있지만이 방법은 Windows가 아닌 Linux에서만 작동하며 내 어셈블리 코드를 멀티 플랫폼으로 만들 수 있습니다.

+0

조건부 어셈블리를 사용할 수 있습니다. NASM에서 그런 식으로 사용하십시오. 'int 80h'을 리눅스 용으로, Windows 용으로는 Windows API 호출을 사용할 수 있습니다 (Windows API에 대해서는 잘 모릅니다). 아주 작은'ELF' 실행 파일을 만들기 위해서 [Really Teensy ELF 실행 파일을 리눅스에서 만들기위한 회오리 바람 튜토리얼] (http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html)이 흥미로울 것입니다. 멀티 플랫폼 어셈블리 프로그래밍에서는별로 도움이되지 않을 것입니다.) – nrz

+0

C의 Hello World 프로그램이 일반적으로 80K를 사용하는 이유는 코드 크기가 아닌 C 런타임 라이브러리 때문입니다. CRT에 연결하지 않으면 EXE가 5-10K 여야합니다. – BitBank

+0

@BitBank, 감사합니다! C 런타임에 의존하지 않도록 코드를 다시 작성하도록 도와 주시겠습니까? – mcandre

답변

1

Windows의 경우 기본 Win32 API 함수 (예 : GetStdHandle()WriteFile())를 stdout에 직접 쓸 수 있습니다.

유닉스 계열 시스템의 경우 stdout에 대해 파일 설명자 1을 사용하여 write() 시스템 호출을 호출 할 수 있습니다.

각각의 작업 방법에 대한 세부 사항은 사용중인 어셈블러와 OS에 따라 다릅니다.

+0

일부 어셈블리 프로그램으로 어셈블하고 Unix 및 Windows에서 작동 가능한 실행 파일을 생성하는 코드 예제를 제공해 주시겠습니까? – mcandre

+0

http://stackoverflow.com/questions/4568306/outputting-hello-world-in-masm-using-win32-functions 및 http://stackoverflow.com/questions/3314919/compile-run-assembler를 참조하십시오. -in-linux –

+0

감사합니다. 그러나이 예제는 OS에 따라 다릅니다. 게다가 그들은 동일한 어셈블러를 사용하지도 않습니다. Windows는 MASM을 사용하고 Linux는 Gas를 사용합니다. – mcandre

0

정적으로 포함하는 대신 C 런타임 라이브러리에 동적으로 링크 할 수 있어야합니다. 나는 리눅스에서 그것을하는 방법을 모르지만, Windows에서는 msvcrt.dll을 사용할 수있다.

+0

고마워. 크기가 줄어들지 만 기본 제공되는 Windows DLL과 같이 OS에 기본적으로 설치되는 부분은 제외하고 실행 파일에 필요한 모든 구성 요소를 포함하는 것을 선호합니다. – mcandre

+0

'msvcrt.dll' *은 Windows 2000 이후 Windows에 내장되어 있다고 생각합니다. –

+0

이 작업을 동적으로 수행하기 위해 makefile에서 링크 명령을 다시 작성할 수 있습니까? – mcandre

0

는 어셈블러 팽창이 가장 가능성이 C lib 디렉토리 종속성에서오고, 다음은 자사의 가능한 가장 작은 크기로 EXE를 축소하는 방법에 대한 모든 세부 사항을 설명하는 프로젝트에 대한 링크입니다 . C 호출을 사용하지 않고 Hello World를 인쇄하도록 코드를 리팩토링하면 유닉스 표준에 커널 호출을하는 인터럽트가 포함되어 있고 Windows에는 이러한 작업을위한 고유 한 VB와 유사한 API가 있기 때문에 대부분 OS 고유의 어셈블리 코드가 필요합니다.

플랫폼 불가지론을 유지하면서 작은 실행 파일을 생성 할 수있는 솔루션을 찾을 수있었습니다. 일반적으로 C 전 처리기 지시문은 그 트릭을 수행하지만, 어떤 어셈블리 언어에도 전처리 구문이 있는지 확실하지 않습니다. 그러나 제어 된 포함 된 어셈블리 코드 파일을 사용하면 비슷한 효과를 얻을 수 있습니다. 래퍼 코드 파일 모음은 OS 관련 어셈블리 코드를 처리 할 수 ​​있지만 포함 된 어셈블리 파일은 나머지 작업을 수행합니다. 그리고 간단한 Makefile은 각각의 빌드 콘솔 명령을 실행하여 원하는 플랫폼에서 각각의 래퍼 코드를 참조 할 수 있습니다.

예를 들어, 나는 이렇게 빨리 작동하는 코드 FASM을 만들 수있었습니다. (아직 실제로 덜 우울한 것으로 puts을 우회하기 위해이 사실을 알려야하지만.) 어쨌든 진행 상황입니다.

0

거의 모든 C 함수는 호출자가 호출 수신자가 호출 수신자 (함수)가 아닌 스택을 조정하는 CDECL 호출 규칙을 사용하기 때문에.

올바르게 작동하는 법을 배우지 않으면 문제가 발생할 수 있습니다. 추적 버그를 더 세게 읽으십시오.

push szLF 
    push esp 
    push fmtint2 
    call printf 
    add  esp, 4 * 3 

    push msg 
    call puts 

    push szLF 
    push esp 
    push fmtint2 
    call printf 
    add  esp, 4 * 3 

실행을하고 전에 풋에 전화 후 번호를 확인할 수 :

이보십시오. 그들은 다른가? 글쎄, 그들은 똑같은 사람이다. 이제 다음을 추가하십시오 :

add  esp, 4 

전화를 걸어 다시 실행하십시오. 숫자는 이제 동일합니까? 즉, 균형 잡힌 스택 포인터가 있고이 함수는 CDECL 호출 규칙을 사용합니다.

관련 문제