Как преобразовать одну цифру в символ в чистой сборке - PullRequest
0 голосов
/ 30 декабря 2010

Что должно произойти, это цифра в eax, например 9, преобразуется в символьную форму '9' и выводится.Я использую nasm на 32-разрядной машине Linux.

section .data
int: dw 9

section .text
global _start

_start:
    mov eax, 9
    add eax, 48
    mov ecx, [eax]

    mov eax, 4
    mov ebx, 1
    mov edx, 1  
    int 0x80

    mov eax, 1
    mov ebx, 0
    int 0x80

При запуске этой программы возникает ошибка сегментации.Я отлаживаю с помощью gdb и получаю ошибку сегментации в строке, где написано mov ecx, [eax].Есть ли способ это исправить?

Ответы [ 3 ]

3 голосов
/ 30 декабря 2010

mov ecx, [eax] означает интерпретировать eax как адрес памяти и скопировать данные в этом месте в ecx.Это попытается разыменовать память по адресу 0x00000039, что вызывает сбой.

Вместо этого, если вы хотите скопировать значение в eax в ecx, используйте mov ecx, eax (без квадратных скобок).

2 голосов
/ 30 декабря 2010

Вы правильно преобразовали число 9, сохраненное в eax, в код ASCII для символа '9', добавив к нему 48, но затем вместо того, чтобы сохранить это значение в буфере для вызова write, выобрабатывают его как адрес памяти и читают с этого адреса в ecx.Адрес памяти (9 + 48 =) 57 находится в области адресного пространства, зарезервированной для перехвата разыменования нулевого указателя, поэтому вы получаете ошибку сегмента.

Вместо этого вы хотите что-то подобное (примечание: я отказываюсь использоватьОбратный синтаксис Intel; скомпилировать с gcc numbernine.s; в 64-битном дистрибутиве вам нужно будет использовать gcc -m32 numbernine.s):

        .data
        .align 4
        .type buf,@object
        .size buf, 2
buf:
        .byte 0
        .byte 10

        .text
        .align 4
        .globl main
        .type main,@function
main:
        leal buf,%ecx
        movb $9,%al
        addb $48,%al
        movb %al,(%ecx)

        subl $12,%esp
        movl $2,8(%esp)
        movl %ecx,4(%esp)
        movl $1,(%esp)
        call write
        addl $12,%esp

        xorl %eax,%eax
        ret

Tangential kibitz: выполнять прямые системные вызовы, только если НЕТАЛЬТЕРНАТИВА.Если библиотека C предоставляет оболочку, используйте ее.Это не проблема для write, но есть целый ряд системных вызовов, для которых оболочка библиотеки C собирается достаточно долго, чтобы оградить вас от изменений в чистом ABI ядра, и вам не нужно это делатьзнать об этом.Кроме того, библиотека C знает, как использовать sysenter (или syscall для 64-битного ABI) и как установить errno.Вот почему я помещаю вещи в стек и вызываю write, а не то, что вы делали.

Кроме того, глупо использовать прямой системный вызов для завершения процесса, когда вы можете просто вернуться из main.

0 голосов
/ 30 декабря 2010

Это означает, что вы воспринимаете значение eax как адрес и ищете его в памяти. Просто снимите скобки.

...