Сборка FreeBSD / amd64 - как читать "ARGC"? - PullRequest
4 голосов
/ 18 ноября 2011

Иногда возвращается правильное значение, иногда 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

%_

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

Ответы [ 2 ]

3 голосов
/ 14 сентября 2012

Я был смущен в том же случае на 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?

1 голос
/ 18 ноября 2011

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

movl %edi, %eax

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

movl    %edi, %eax
ret
...