Аргументы командной строки Linux NASM как целые числа - PullRequest
3 голосов
/ 29 марта 2012

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

section .text
    global _start

_start:
    pop eax
    pop ebx
    pop ecx

_exit:
    mov eax, 1
    mov ebx, 0
    int 0x80

Компиляция/ linking с:

$ nasm -f elf -o test.o test.asm
$ gcc -o test test.o

Запуск его в GDB с аргументом "5":

$ gdb test
...
(gdb) b _exit
Breakpoint 1 at 0x8048063
(gdb) r 5
Starting program: /home/rich/asm/test 5

Breakpoint 1, 0x08048063 in _exit ()
(gdb) i r
eax            0x2      2
ebx            0xbffff8b0       -1073743696
ecx            0xbffff8c8       -1073743672
edx            0x0      0
esp            0xbffff78c       0xbffff78c
ebp            0x0      0x0
...

Так что здесь eax имеет смысл - это 0x2 или 2, argc.Мой вопрос: как мне получить значение «5» (или 0x5) в регистр?Насколько я понимаю, ecx - это указатель на мое значение 5, так как я могу «преобразовать» его в пригодную для использования цифру, то есть в ту, с которой я могу делать арифметические действия?

Ответы [ 2 ]

2 голосов
/ 29 марта 2012

Что ты хочешь с этим делать? Ваше понимание верно: ядро ​​помещает счетчик argc на вершину стека, под которым находится argv [0] ... argv [argc-1] в обратном порядке (т. Е. Верхняя часть стека / самый низкий адрес памяти содержит первый аргумент). Вы можете проверить это с помощью gdb для любого двоичного файла в системе:

$ echo "int main(){return 0;}" > test.c
$ gcc test.c
$ gdb ./a.out
(gdb) b _start
(gdb) r A B C D E
(gdb) p ((void**)$rsp)[0]
$2 = (void *) 0x6
(gdb) p (char*)((void**)$rsp)[1]
$4 = 0x7fffffffeab7 "/home/andy/a.out"
(gdb) p (char*)((void**)$rsp)[2]
$5 = 0x7fffffffeac8 "A"
(gdb) p (char*)((void**)$rsp)[3]
$6 = 0x7fffffffeaca "B"
(gdb) p (char*)((void**)$rsp)[4]
$7 = 0x7fffffffeacc "C"
(gdb) p (char*)((void**)$rsp)[5]
$8 = 0x7fffffffeace "D"
(gdb) p (char*)((void**)$rsp)[6]
$9 = 0x7fffffffead0 "E"

Возможно, вы спрашиваете, как разобрать строки? Это более сложный вопрос.

1 голос
/ 02 сентября 2012

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

Проблема, с которой, я думаю, вы столкнулись, заключается в том, что «5», которую вы передаете своей программе, не сохраняется как целое число 5, как можно предположить.Аргумент передается вашей программе в виде символа, и, как указал Энди, у вас будет указатель на байт, содержащий 0x35, который является целочисленным значением, представляющим символ ASCII 5, а не указатель на целочисленное значение 5.

Чтобы использовать ваш аргумент в качестве целого числа, вам нужно будет преобразовать байт в его целочисленный эквивалент, как определено в таблице ASCII - в противном случае вы обнаружите, что вы передаете символ 5, но все математические операции, которые вы пытаетесь выполнитьс этим будет использовать 53 (0x35), потому что это представляет 5 в ASCII.

Пример того, как выполнить это преобразование, можно найти в функции rsi_to_bin в примере программы asm здесь .После того, как вы преобразовали код ascii в его действительный целочисленный эквивалент, у вас будет правильное число, которое вы передали, и вы сможете выполнять с ним любую арифметику, какую захотите.Чрезвычайно простым примером будет просто вычесть 48 из входных данных - это будет работать, если вы передадите только одно целое число со значением 0-9.

...