Сборка x86 pushl / popl не работает с «Ошибка: суффикс или операнды неверны» - PullRequest
27 голосов
/ 30 марта 2011

Я новичок в программировании на ассемблере, работаю через Программирование с нуля на рабочем столе 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'

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

Ответы [ 5 ]

31 голосов
/ 30 марта 2011

В 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байт в машинном коде (для полезной нагрузки эксплойта))


Похожие:

14 голосов
/ 29 июля 2013

Недавно я тоже начал следовать этим примерам, я обнаружил следующее:

  1. Добавьте .code32 в начало вашего кода сборки
  2. Собрать с флагом --32
  3. Ссылка с флагом -m elf_i386

Вы можете увидеть мой пример здесь

7 голосов
/ 30 марта 2011

Вам нужно заменить последовательность push / pop на

pushq $1       # push the value 1 onto the stack
popq %rax      # pop 1 off the stack and into the %eax register

Обратите внимание, что сообщение об ошибке " суффикс или операнд недействителен", вы проверили только вторую часть логического OR в сообщении об ошибке, возможно, потому что вы не были точно уверены, что означает суффикс : это «л».

Изменить: Пожалуйста, смотрите Томас ответ для объяснения, почему ваш код не будет работать в любом случае, даже если он собирается.

2 голосов
/ 28 января 2014

Я столкнулся с этой ошибкой, работая через ту же книгу. Я создал следующий скрипт оболочки (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
0 голосов
/ 27 ноября 2017

Вы можете нажать любое значение без команды push, как эта

decq %rsp
movb $0, (%rsp)

вставка 1 байта в стек и поп после

movb (%rsp), %al
incq %rsp

и любой другой размер. Поскольку компилятор не генерирует никаких ошибок, и все будет работать хорошо! Для адресации можно использовать регистр rbp вместо rsp. Теперь разрешено.

...