FreeBSD/amd 64 assembly -如何从_start读取“ARGC”?

6qqygrtg  于 2023-06-06  发布在  其他
关注(0)|答案(2)|浏览(209)

有时会返回正确的argc值,有时是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

%_

我对汇编有点陌生,但我很有信心,获得参数计数就像在Linux中从堆栈中弹出一样容易,在Linux中,System V ABI记录RSP在一个新的execve进程中指向argc
是我做错了什么,还是真的搞砸了?

krugob8w

krugob8w1#

我在FreeBSD 9.0/amd 64上遇到了同样的问题。我所做的是(我使用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/amd 64/amd 64/machdep. c(exec_setregs)中找到了以下代码。

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

编辑:machdep.c已被拆分,现在可以在exec_machdep.c中找到此函数
这些行看起来像是说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吗?

irlmq6kh

irlmq6kh2#

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

movl %edi, %eax

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

movl    %edi, %eax
ret

相关问题