Я пытаюсь изучить сборку x86. Я использую книгу Assembly Language - Step by Step, Programming With Linux
(и я должен сказать, что она очень хороша). На данный момент я многому научился, но я чувствую, что мне также следует бросать себе вызов, чтобы оставаться впереди во многих отношениях, чтобы я мог учиться быстрее, работая (я могу следовать за мной, учиться сверху вниз, но я нахожу это утомительным). медленный).
Итак, я подумал, что было бы неплохо попытаться перемножить два регистра (32-битных) и затем вывести данные на консоль.
Проблема в том, что когда я запускаю программу (я использую NASM, как и в книге, но без отладчика Insight), я получаю ошибку сегментации. Я проделал изрядную часть отладки в gdb с помощью этого небольшого молотка, но по какой-то причине я не могу понять, в чем проблема.
Я хотел бы знать, почему я получаю сообщение об ошибке сегментации и как правильно сделать выговор за эту проблему. Кроме того, если комментарии, которые я сделал в коде, не совпадают с тем, что именно происходит, я был бы признателен, если бы кто-нибудь меня поправил.
Вот мой код до сих пор (он хорошо прокомментирован)
Спасибо.
те кодез
section .data
;TODO
section .bss
valueToPrint: resb 4 ;alloc 4 bytes of data in 'valueToPrint'
section .text
global _start
_mul:
mov eax, 0x2A ;store 42 in eax
mov edx, 0x2A ;store 42 in edx
mul eax
ret
_safe_exit:
mov eax, 1 ;initiate 'exit' syscall
mov ebx, 0 ;exit with error code 0
int 0x80 ;invoke kernel to do its bidding
_start:
nop ;used to keep gdb from complaining
call _mul ;multiply the values
mov [valueToPrint], eax ;store address of eax in the contents of valueToPrint
mov eax, 4 ;specify a system write call - aka syswrite
mov ebx, 1 ;direction used to make the syswrite call output to console - i.e. stdout
mov dword [ecx], valueToPrint ;store valueToPrint in ecx: ecx represents the syswrite register
int 0x80 ;invoke kernel based on the given parameters
call _safe_exit
Изменить
Кроме того, я использую Arch Linux, если это имеет значение.
mul eax
, которое умножает eax на eax... поскольку вы используете 42 и в eax, и в edx, вы получаете (ну, вы ДОЛЖНЫ получить) правильный ответ, но вы не включает значение в edx. @Adam Rosenfield (ниже) имеет правильный ответ, хотя вы не создаете строку TEXT/ASCII для печати в первую очередь. на самом деле сборка ничего автоматически не делает для вас. Вот почему у вас так много контроля... но вы должны говорить ему, как все делать. Вы не создаете текстовую строку, чтобы указать ecx для печати. (вам также нужна длина) - person lornix   schedule 29.06.2012mul
(умножение) умножает значение в eax (ax/rax и т. д.) на все, что указано, и помещает результирующее 64-битное значение в EDX:EAX... поэтому, если вы ищете полный ответ, не забудьте также также используйте значение edx. 42 * 42 = 1764, так что вы далеки от ответа, переносимого в edx, но вы все равно должны знать, что происходит, поэтому вы можете ожидать, что edx изменится и будет использоваться при необходимости. - person lornix   schedule 29.06.2012jmp
обратиться к ней. Да, система сбрасывает все, когда программа выходит... но опять же, вы должны знать, как все работает.call _save_exit
отлично работает, но для меня он оставляет значение в стеке. Придирчивые вещи. Мои извинения. Я начал сборку на машине 16K еще когда... Память была дорогой, а код писался туго. Я до сих пор так думаю, даже с 8G RAM. Как правило, меньший работает быстрее. - person lornix   schedule 29.06.2012mul edx
. Прошу прощения за придирки... сборка - это круто, но надо уметь жонглировать всем, так как на самом деле это совсем вам не поможет, а незнание того, как вещи взаимодействуют, вас укусит. - person lornix   schedule 29.06.2012