2011-11-18 60 views
4

有时,正确的值会返回,有时候是0,有时候(看似)是随机数......都来自同一个可执行文件。FreeBSD/amd64程序集 - 如何阅读“ARGC”?

.section .text 
.global _start 
_start: 
    movq $1, %rax 
    popq %rdi 
    syscall 

例如:

%as -o this.o this.s ; ld -o this this.o 

%./this; echo $? 
1 

%./this 1; echo $? 
0 

%./this 1 2; echo $? 
3 

%./this 1 2 a; echo $? 
4 

%./this 1 2 a f; echo $? 
0 

%_ 

我一种新的组装,但我非常有信心获得参数计数是因为它弹出关闭堆栈一样容易。 我做错了什么,还是这真的搞砸了?

+0

尝试在调试器中运行它以查看堆栈布局是否符合您的期望。 – user786653

+0

谢谢,我已经有一段时间了,通常8(%esp)有argc,但有时候不会,我想我会继续努力吧! :) – timmmay

回答

3

我感到困惑在FreeBSD 9.0/amd64上也是如此。 (我使用NASM的汇编),我所做的是:

$ cat foo.asm 
global _start 
_start: 
     mov  rax, 4   ; write 
     mov  rdi, 1   ; stdout 
     mov  rsi, rsp  ; address 
     mov  rdx, 16   ; 16bytes 
     syscall 

     mov  rax, 1   ; exit 
     syscall 
$ nasm -f elf64 foo.asm && ld -o foo foo.o 
$ ./foo | hd 
00000000 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................| 
00000010 
$ ./foo 2 | hd 
00000000 02 00 00 00 00 00 00 00 b8 dc ff ff ff 7f 00 00 |................| 
00000010 
$ ./foo 2 3 | hd 
00000000 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 |................| 
00000010 
$ ./foo 2 3 4 | hd 
00000000 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................| 
00000010 
$ ./foo 2 3 4 5 | hd 
00000000 05 00 00 00 00 00 00 00 b0 dc ff ff ff 7f 00 00 |................| 
00000010 

我预期的argc在RSP,但事实并非如此。

我猜想内核(图像激活器)设置寄存器。我搜索了源代码树,在/usr/src/sys/amd64/amd64/machdep.c(exec_setregs)中找到了以下代码。

 regs->tf_rsp = ((stack - 8) & ~0xFul) + 8; 
     regs->tf_rdi = stack;   /* argv */ 

这些行看起来是说rsp是对齐的,实际数据是rdi。我改变了我的代码,并获得了预期的结果。

$ cat foo.asm 
global _start 
_start: 
     push rdi 
     mov  rax, 4   ; write 
     mov  rdi, 1   ; stdout 
     pop  rsi 
     mov  rdx, 16   ; 16bytes 
     syscall 

     mov  rax, 1   ; exit 
     syscall 
$ nasm -f elf64 foo.asm && ld -o foo foo.o 
$ ./foo | hd 
00000000 01 00 00 00 00 00 00 00 b0 dc ff ff ff 7f 00 00 |................| 
00000010 
$ ./foo 2 | hd 
00000000 02 00 00 00 00 00 00 00 a8 dc ff ff ff 7f 00 00 |................| 
00000010 
$ ./foo 2 3 | hd 
00000000 03 00 00 00 00 00 00 00 a8 dc ff ff ff 7f 00 00 |................| 
00000010 
$ ./foo 2 3 4 | hd 
00000000 04 00 00 00 00 00 00 00 a8 dc ff ff ff 7f 00 00 |................| 
00000010 
$ ./foo 2 3 4 5 | hd 
00000000 05 00 00 00 00 00 00 00 a8 dc ff ff ff 7f 00 00 |................| 
00000010 

你可以试试偏下?

1

对于FreeBSD的标准调用约定,你想:

movl %edi, %eax 

最短的完整的程序,其返回的状态将等于它传递参数的个数是:

movl %edi, %eax 
ret 
+0

嗯......那个seg在我身上发生了故障。我使用64位而不是32位,所以我不知道这是否有所作为。 – timmmay

+1

这将用于'main'函数,它被调用并返回到'_start'。他正在尝试编写一个'_start'函数,它接收堆栈中的参数并且不能返回。 – ughoavgfhw

+0

谢谢,它在主函数中工作正常,但没有启动。我已经重读了amd64 abi并尝试了几次调试(尽管我没有经验过使用调试器)。如果有人能够协助,我将不胜感激。谢谢! :) – timmmay