Есть несколько проблем в вашем коде.
От 64bit Ubuntu
и pushq %rax
Я полагаю, что вы пытаетесь сделать 64-битный исполняемый файл.
Если это так, то ...
здесь:
pushq %rax
pushq $output
call printf
addl $8, %esp
вы не правильно сбалансировать стек после вызова функции. Вы все еще помните, что это 64-битный код? Вам нужно добавить к rsp
, а не esp
. Кроме того, если вы нажмете 2 8-байтовых параметра, вам нужно удалить ровно 2 8-байтовых параметра, а это значит, что вам нужно добавить 16, а не 8.
Но это даже хуже. В 64-битном режиме параметры передаются по-разному. Первые параметры указаны в регистрах rdi
, rsi
, rdx
, rcx
, r8
и r9
. Итак, что дает нам:
movq %rax, %rsi
movq $output, %rdi
movq $0, %rax ; number of vector registers used for var-arg-function printf()
call printf
Здесь:
inc %edi
Вы только что уничтожили значение rdi
вызовом и с помощью этого регистра для передачи параметров. Вам нужно вручную нажать rdi
перед вызовом, а затем потушить его. Или вы можете сохранить его в глобальной переменной. Если вы решите нажать и поп, убедитесь, что указатель стека rsp
всегда выровнен на 16 байт перед любой командой call
.
Здесь:
movl $0, %ebx
movl $1, %eax
int $0x80
вы используете 32-битный интерфейс системного вызова. В 64-разрядных программ, которые вы должны использовать 64-битный интерфейс системного вызова:
movq $60, %rax ; sys_exit
movq $0, rdi ; return 0 (success)
syscall
Теперь, я думаю, что это одна может иметь проблемы тоже:
movl $0, %edi
loop :
movl values(, %edi, 4), %eax
В общем, вы не должны быть используя 32-разрядные регистры и 32-разрядные команды в вычислениях адресов в 64-битном коде. Я бы изменить его на:
movl $0, %rdi
loop :
movl values(, %rdi, 4), %eax
Если ни один из этих двух работ, так как адрес values
более 2 Гб от rip
(факт: перемещения ограничены 32-разрядных целых чисел в памяти операндов в большинстве инструкций в 64-битном режиме, и большинство из них не имеют кодировки операнда памяти только для перемещения в 64-битном режиме, они используют rip
- относительную адресацию там), вам нужно будет вручную добавить 64-разрядный адрес values
, а индекс в массив, умноженный на 4. Убедитесь, что вы делаете 64-битное дополнение без каких-либо усечений на этом пути.
Must-гласит:
Я думаю, что большинство ваших регистров 'e__' должно быть' r__'. Похоже, что это было написано как сборка x86 и принудительно перенесено на x64 без внесения всех необходимых изменений. – Mysticial
Я пробовал, но это тоже не сработает. – Nmzzz
Собранный как 64-битный? Тогда стек не DWORD, а QWORD выровнен, поэтому ваше добавление 8 к rsp неверно, должно быть добавлено 16 к rsp после вашего вызова printf. – Gunner