Вы правильно преобразовали число 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
.