Сборка FreeBSD/amd64 — как читать 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

%_

Я новичок в ассемблере, но я был уверен, что получить количество аргументов так же просто, как вытолкнуть его из стека. Я что-то делаю не так, или это просто действительно испорчено?


person timmmay    schedule 18.11.2011    source источник
comment
Попробуйте запустить его в отладчике, чтобы увидеть, соответствует ли макет стека вашим ожиданиям.   -  person user786653    schedule 18.11.2011
comment
Спасибо, я некоторое время работал с gdb, и обычно 8(%esp) имеет argc, но иногда нет, думаю, я продолжу работать над этим! :)   -  person timmmay    schedule 18.11.2011


Ответы (2)


Меня смутил тот же случай на 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

Можешь попробовать рди?

person Tomohiko Sumi    schedule 14.09.2012

Для стандартного соглашения о вызовах FreeBSD вам нужно:

movl %edi, %eax

Самая короткая полная программа, состояние возврата которой будет равно количеству переданных ей параметров:

movl    %edi, %eax
ret
person David Schwartz    schedule 18.11.2011
comment
хм... этот сегмент обвинил меня. Я использую 64-битную, а не 32-битную, поэтому я не знаю, имеет ли это значение. - person timmmay; 18.11.2011
comment
Это было бы для функции main, которая вызывается и возвращается к _start. Он пытается написать функцию _start, которая получает свои параметры в стеке и не может вернуться. - person ughoavgfhw; 18.11.2011
comment
Спасибо, он отлично работает в основной функции, но не при запуске. Я перечитал amd64 abi и пару раз пытался отладить (хотя у меня нет опыта использования отладчика). Если кто-то может помочь, я был бы очень признателен. Спасибо! :) - person timmmay; 18.11.2011