Подтвердить что ты не робот

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, действительны. Это не совсем вопрос отладки - так что случилось с моим кодом? Или это мой ассемблер?

4b9b3361

Ответ 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. Теперь разрешено.