Вывод целых чисел в сборку в Linux
Это нужно сделать в чистой сборке (т.е. нет библиотек или вызовов на C).
Я понимаю суть проблемы: нужно разделить целое число на 10, преобразовать однозначный остаток в ASCII, вывести его, а затем повторить процесс с помощью частного.
Но по какой-то причине он просто не работает. Я использую NASM на x86.
Вот то, что у меня есть до сих пор (ничего не выводит, но не вызывает никаких ассемблерных ошибок):
; integer to output is stored in eax
mov ecx, 10 ; for base 10
loop:
div ecx ;EAX contains the quotient, EDX the remainder
; Do something to EDX to convert it to ASCII, not sure if this is correct
add edx, '0'
push eax ;We'll be playing with EAX to output EDX, save EAX to the stack
mov eax, 4 ; sys_write
mov ebx, 1 ; to STDOUT
mov ecx, edx
mov edx, 1
int 0x80
pop eax ;restore EAX
cmp eax, 0 ;If EAX is 0, our job is done
jnz loop
Есть несколько вопросов, подобных этому (а именно this и this), но Я потерян в реализации. Этот вопрос (для DOS) также был полезен, но я все еще смущен.
Мне, должно быть, что-то не хватает. Мысли?
Ответы
Ответ 1
Есть еще две проблемы. за коррупцией ecx
, о которой упоминал @sarnold:
-
div ecx
делит 64-битное значение edx:eax
на ecx
, поэтому вам нужно убедиться, что перед делением вы установите edx
на 0.
-
Второй аргумент системного вызова write
(в ecx
) должен быть указателем на буфер, содержащий символ, который вы хотите распечатать, а не сам символ.
Один из способов решить вторую проблему - нажать регистр, содержащий символ, который вы хотите распечатать в стеке, а затем назначить указатель стека esp
на ecx
(указатель стека указывает на самый последний нажатый элемент, а x86 хранит значения little-endian, поэтому первый байт - это младшие 8 бит). например.
push edx ; save value on stack
mov eax, 4 ; sys_write
mov ebx, 1 ; to STDOUT
mov ecx, esp ; first byte on stack
mov edx, 1 ; length = one byte
int 0x80
pop edx ; remove what we pushed (or "add esp, 4" would do just as well here;
; we don't need the actual value again)
Этого должно быть достаточно, чтобы получить некоторый результат...
(Но в этот момент вы можете заметить "особенность" вашего алгоритма и хотите переосмыслить, как вы храните цифры, которые производятся подразделением!)
Ответ 2
Вы правильно установите ecx
в 10
в верхней части своей подпрограммы, но перепишите ecx
позже:
mov eax, 4 ; sys_write
mov ebx, 1 ; to STDOUT
mov ecx, edx ;;; oops -- lost the 10
mov edx, 1
int 0x80
Попробуйте переместить loop
на одну строку, поэтому ecx
будет повторно инициализироваться до 10
каждый раз через цикл.