Ответ здесь указывает, что ESP + 4
указывает на argv[0]
. Но я не могу заставить его работать:
.section .text
.globl _start
_start:
movl 8(%esp), %ebx
movl $1, %eax
int $0x80
И теперь, когда я пытаюсь выполнить это:
$ as --32 argv.s -o argv.o
$ ld -m elf_i386 argv.o -o argv
$ ./argv 2
$ echo $?
16
Он отображает 16
, хотя я ожидаю здесь 16. Что я делаю неправильно ?
Используйте GDB для пошагового выполнения кода, чтобы вы могли выгружать стековую память более чем на 1 байт за раз и легко просматривать значение указателя + то, на что он указывает.
@PeterCordes Спасибо, пошаговое выполнение через GDB было полезным.
Благодаря комментарию Питера я наконец смог найти ответ. Поскольку argv
- это указатель на указатель на char
, при первом разыменовании вы получите адрес, который является указателем на символ. Повторное разыменование даст вам желаемый результат:
.section .text
.globl _start
_start:
movl 8(%esp), %ebx
movl (%ebx), %ebx
movl $1, %eax
int $0x80
При его выполнении:
$ ./argv 1
49
49 - ожидаемый результат, который представляет собой Символ ASCII1
.
0x10
выглядит разумным значением для младшего байта указателя. Вы получите0
, если нет аргументов, поэтомуargv[1]
имеет значение NULL, верно? В любом случае, разыменуйте в другой раз, если вы хотите, чтобы байт содержал код символа ASCII из указанной строки. (помните, что статус выхода Linux имеет ширину всего 1 байт.)