我尝试编写一个简短的32位汇编程序来测试mac os x中的系统调用。
我编写了下面显示的第一个版本,调用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
在此之后,我决定写另一个版本使用mkdir()在“/ tmp”中创建一个新目录,但是我失败了。 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 :(得分:1)
Here我在MacOS上找到了一个简单的系统调用指南。根据我的阅读,我假设%eax
寄存器的值是唯一一个通过寄存器传递给系统调用的寄存器。必须从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
电话似乎也没有问题(我不确定,我对这种系统调用方式不是很熟悉)
subl %esp, $8 /* unused EDX and ECX */
pushl $0 /* for EBX */
movl $1, %eax
pushl %eax /* unused EAX */
int 0x80
修改强>
在挖掘了关于BSD系统调用主题的一些材料之后,我还发现了一个建议将堆栈16字节对齐的源。这意味着当你用少于4个参数调用一个系统调用时,你应该推送额外的双字,当你调用一个带有5个或全6个参数的系统调用时,你也应该推送一些双字(如果空闲)ESI
, EBP
和ESP
。