【问题标题】:FreeBSD/amd64 assembly - how to read "ARGC"?FreeBSD/amd64 程序集 - 如何阅读“ARGC”?
【发布时间】:2012-09-14 15:38:47
【问题描述】:

有时会返回正确的值,有时会返回 0,有时会(看似)随机数...都来自同一个可执行文件。

.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

%_

我对汇编有点陌生,但我非常有信心获得参数计数就像将其从堆栈中弹出一样简单。 是我做错了什么,还是真的搞砸了?

【问题讨论】:

  • 尝试在调试器中运行它,看看堆栈布局是否符合您的期望。
  • 谢谢,我已经 gdb 了一段时间,通常 8(%esp) 有 argc,但有时没有,我想我会继续努力的! :)

标签: assembly freebsd


【解决方案1】:

我在 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

你可以试试 rdi 吗?

【讨论】:

    【解决方案2】:

    对于 FreeBSD 的标准调用约定,您需要:

    movl %edi, %eax
    

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

    movl    %edi, %eax
    ret
    

    【讨论】:

    • hmmm...那个段对我有问题。我使用的是 64 位而不是 32 位,所以我不知道这是否会有所不同。
    • 这将用于main 函数,该函数由_start 调用并返回。他正在尝试写一个_start函数,它在堆栈上接收它的参数并且不能返回。
    • 谢谢,它在 main 函数中运行良好,但不是 start。我重读了 amd64 abi 并尝试了几次调试(尽管我没有使用调试器的经验)。如果有人可以提供帮助,我将不胜感激。谢谢! :)
    猜你喜欢
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-06
    • 1970-01-01
    • 2014-06-02
    • 2011-01-31
    相关资源
    最近更新 更多