ASM вызов Printf

movl %ebx, %esi
movl $.LC1, %edi
movl $0, %eax
call printf

Я использую следующий ассемблерный код для печати того, что находится в регистре EBX. Когда я использую

movl $1,%eax
int 0x80

и echo $? Я получаю правильный ответ, но ошибка сегментации в первом случае. Я использую GNU Assembler и AT&T синтаксис. Как я могу исправить эту проблему?

2 ответа

Судя по коду, вы, вероятно, находитесь в 64-битном режиме (пожалуйста, подтвердите), в этом случае указатели имеют 64-битный размер. Вы должны заменить movl $.LC1, %edi от leaq .LC1, %rdi (или же leaq .LC1(%rip), %rdi) и это должно работать.

Кроме того, убедитесь, что:

  • вы сохраняете ценность rbx в вашей функции
  • указатель стека выравнивается по мере необходимости

Этот код работает для меня в 64 бит:

.globl main
main:
    push %rbx
    movl $42, %ebx
    movl %ebx, %esi
    leaq .LC1, %rdi
    movl $0, %eax
    call printf
    xor  %eax, %eax
    pop  %rbx
    ret

.data
    .LC1: .string "%d\n"

Редактирование: Как заметил Джестер, этот ответ относится только к x86 (32 бит) asm, тогда как приведенный пример более вероятен для x86-64.

Это потому, что printf имеет переменное количество аргументов. Вызов printf не восстанавливает стек для вас, вам нужно сделать это самостоятельно.

В вашем примере вам нужно написать (32-битная сборка):

push %ebx
push $.LC1
call printf
add $8, %esp  // 8 : 2 argument of 4 bytes
Другие вопросы по тегам