X86 Сборка pushl/popl не работает с "Ошибка: суффикс или операнды недействительны"
Я новичок в сборочном программировании, работая через Programming Ground Up на рабочем столе Ubuntu x86_64 с ассемблером GNU v2.20.1.
Мне удалось собрать/связать выполнение моего кода, пока я не получу использование команд pushl/popl для управления стеком. Следующий код не может быть собран:
.section .data # empty
.section .text
.globl _start
_start:
pushl $1 # push the value 1 onto the stack
popl %eax # pop 1 off the stack and into the %eax register
int $0x80 # exit the program with exit code '1'
Используя "как test.s -o test.o", эти ошибки появляются на терминале, а test.o не создается:
test.s: Assembler messages:
test.s:9: Error: suffix or operands invalid for 'push'
test.s:10: Error: suffix or operands invalid for 'popl'
Я проверил документацию, и операнды, которые я использую для pushl и popl, действительны. Это не совсем вопрос отладки - так что случилось с моим кодом? Или это мой ассемблер?
Ответы
Ответ 1
В 64-битном режиме вы не можете нажимать и вызывать 32-битные значения; вам нужны pushq
и popq
.
Кроме того, вы не получите правильный выход таким образом. В 32-битном x86 вам нужно установить %eax
в 1, чтобы выбрать системный вызов exit()
, и установить %ebx
в код выхода, который вы действительно хотите. В 64-разрядной версии x86 (что вы используете), соглашения разные: номер системного вызова для exit()
равен 60, а не 1; первый параметр системного вызова находится в %rdi
, а не %rbx
; код операции вызова системного вызова не является int $0x80
, а специальным кодом операции x86-64 syscall
.
Что приводит к:
.section .data
.section .text
.globl _start
_start:
pushq $60
popq %rax
pushq $1
popq %rdi
syscall
(каждая последовательность push
/pop
может быть заменена простым mov
(например, mov $60, %eax
)), я предполагаю, что вы пытаетесь явно протестировать push
и pop
, оптимизировать для размер кода или избегать 0
байтов в машинный код (для полезной нагрузки эксплойта))
Связанный:
Ответ 2
Недавно я начал также следовать этим примерам, я нашел следующее:
- Добавьте
.code32
в начало кода сборки
- Соберите флаг
--32
- Ссылка с флагом
-m elf_i386
Вы можете увидеть мой пример здесь
Ответ 3
Вам нужно заменить последовательность push/pop на
pushq $1 # push the value 1 onto the stack
popq %rax # pop 1 off the stack and into the %eax register
Обратите внимание, что сообщение об ошибке " суффикс или операнд недействителен", вы только проверили вторую часть логического OR
в сообщении об ошибке, возможно, потому, что вы не совсем точно знали, что такое суффикс означает: это "l".
Изменить: Пожалуйста, обратитесь к Томасу за объяснением, почему ваш код не будет работать, даже если он собирается.
Ответ 4
Я столкнулся с этой ошибкой, работая в той же книге.
Я создал следующую оболочку script (att.sh):
#!/bin/sh
as --32 $1.s -o $1
ld -melf_i386 $1.o -o $1
./$1
echo $?
Что я тогда выполнил и выполнил (предположив входной файл myfile.s):
chmod +x ./att.sh
./att.sh myfile
Ответ 5
Вы можете нажать любое значение без команды push
decq %rsp
movb $0, (%rsp)
нажмите 1 байт в стеке
и поп после
movb (%rsp), %al
incq %rsp
И любой другой размер. Поскольку компилятор не генерирует никаких ошибок, и все будет работать хорошо! Для адресации может использоваться rbp-регистр вместо rsp. Теперь разрешено.