2014-07-10 2 views
0

Mac OS X에서 시스템 호출을 테스트하기 위해 짧은 32 비트 어셈블리 프로그램을 작성하려고합니다.mac os x의 32 비트 어셈블리에서 시스템 호출을 만들지 못했습니다.

아래와 같이 첫 번째 버전을 작성하고 write() 함수를 호출하여 화면에 문자열을 인쇄합니다. 그것은 효과가있다.

.data 
str: 
    .ascii "Hello World\n" 

.text 
.globl _main 
_main: 
    pushl $12 
    pushl $str     
    pushl $1     
    movl $4, %eax    
    subl $4, %esp    
    int  $0x80    
    addl $16, %esp   
    pushl $0     
    movl $1, %eax    
    subl $12, %esp   
    int  $0x80 

이 후, 나는 또 다른 버전 "/ tmp를"새로운 디렉토리를 만들 MKDIR()를 사용 쓰기로 결정,하지만 난 실패했습니다. mkdir()의 시스템 호출 번호는 0x88이고 내 코드는 아래에 나와 있습니다. 아무도 내가 틀렸다고 말할 수 있습니까? 매우 감사합니다.

.data 
path: 
    .ascii "/tmp/new_dir" 

.text 
.globl _main 
_main: 
    nop 
    pushl $path 
    pushl $0x1ff 
    movl $0x88, %eax 
    subl $8, %esp 
    int  $0x80 
    addl $16, %esp 

    pushl $0     
    movl $1, %eax    
    subl $12, %esp   
    int  $0x80 
+0

왜'subl $ 8' ?! –

+0

OS X은 스택이 16 바이트로 정렬되어야합니다. 나는 이미 8 바이트를 밀고있다. 그래서 스택을 정렬하려면'subl $ 8 '이 필요합니다. –

+0

스택 정렬은 인수를 푸시하기 전에 * 발생해야합니다. 그렇지 않은 경우, 피 호출자가 인수를 어디에서 찾을 수 있는지 어떻게 알 수 있습니까? 진행 상황에 대한 내 답변 [here] (https://stackoverflow.com/questions/21367494/understanding-osx-16-byte-alignment/21371636#21371636)을 참조하십시오. –

답변

1

Here MacOS에서 syscalls에 대한 간단한 안내서를 발견했습니다. 내가 읽은 바로는 %eax 레지스터의 값이 레지스터로 syscall에 전달 된 유일한 값이라고 가정합니다. 나머지 레지스터는 EDX으로 시작하는 스택에 푸시되어야합니다.

+----------+------------------------+--------------------------------+ 
| Register |   Use   |   Location   | 
+----------+------------------------+--------------------------------+ 
| EAX  | Unused, just a padding | [ESP]       | 
| EBX  | Name of directory  | [ESP+4]      | 
| ECX  | Access     | [ESP+8]      | 
| EDX  | Unused     | Unused, but let's say [ESP+12] | 
+----------+------------------------+--------------------------------+ 

이 표에 따르면, 당신의 mkdir 호출은 다음과 같아야합니다

pushl $0  /* for EDX, unused */ 
pushl $0x1FF /* for ECX */ 
pushl $path /* for EBX */ 
movl $0x88, %eax 
pushl %eax  /* for EAX but unused */ 
int $0x80 
addl $16, %esp /* clean up */ 

가에 추가

, 당신의 exit 통화 중 (잘 모르겠어요, 내가 'OK 될 것 같지 않습니다 하지의이 방법으로 잘 알고 있어요 콜 - 보내고)

subl %esp, $8 /* unused EDX and ECX */ 
pushl $0  /* for EBX */ 
movl $1, %eax 
pushl %eax /* unused EAX */ 
int 0x80 

편집 : 발굴 후 BSD syscalls 주제에 관한 몇 가지 자료는 스택 16 바이트 정렬을 권장하는 소스를 찾았습니다. 이것은 매개 변수가 4 개 미만인 시스템 콜을 호출 할 때 추가 더블 워드를 넣어야 함을 의미하며, 5 개 또는 6 개의 매개 변수를 사용하여 시스템 콜을 호출 할 경우 ESI, EBPESP에 대한 더블 워드를 입력해야합니다.

+0

답변 해 주셔서 감사합니다. 그러나 여섯 가지 매개 변수를 다루는 방법을 궁금해합니다. 어떤 책은 6 개 이상의 매개 변수가 필요한 경우, '% ebx' 레지스터는 입력 매개 변수의 메모리 위치에 대한 포인터를 포함하는 데 사용되며 순차적 순서로 저장됩니다. 6 개 이상의 매개 변수를 처리하는 예제를 보여 주시겠습니까? –

+0

필자가 얻은 한, 특정 시스템 호출은 일반적으로 추가 매개 변수에 대한 자체 포맷을 가지고 있습니다. 어떤 시스템 콜에 관심있어? – user35443

+0

32 비트 abi를 읽지는 않았지만, 몇 가지 범용 레지스터를 사용한다고 가정하고 나머지는 스택에 있다고 가정합니다. 적어도 64 비트 abi가 지정하는 것입니다. –