- Вы слишком усложняете это с большим количеством инструкций, чем необходимо
a
будет argv[1]
, но вы загружаете argv[0]
(условно название программы, но может бытьNULL-указатель или произвольная строка, если ваша программа вызывается с execve()
из чего-то отличного от обычной оболочки). - вы сравниваете
"a"
со значением указателя, а не с данными, указанными на строку.
т.е. то, что вы написали на C-версии:
if( (intptr_t)argv[0] == "a" ){
success:
}
Для индекса с постоянной времени сборки вы должны просто использовать смещение вместо индекса,Вы можете написать его так, чтобы он выглядел хорошо для людей, используя выражение времени сборки, например 1 * 8
или 0 * 8
.
global main
main:
cmp edi, 2
jb too_few_args ; if(argc<2) avoid segfaults in both of the next 2 insns
mov rdx, [rsi + 8*1] ; r14 = argv[1]
cmp byte [rdx], "a" ; argv[1][0] == 'a'
je success
...
success:
xor eax,eax
ret ; return 0
r14
- это регистр с сохранением вызовов в x86-64Система V ABI, поэтому, если вместо call exit
возвращается main
, вы должны оставить R14 с тем же значением, которое было при входе. Какие регистры сохраняются при вызове функции linux x86-64
RDX имеет блокировку вызовов, поэтому это хороший выбор для чистого регистра.
Он также сохраняетбайт размера кода для использования RDX или какого-либо другого регистра, который не нуждается в префиксе REX вместо R8..15.Qword mov
всегда будет нуждаться в префиксе REX, но байт cmp
не будет.