Вывод целых чисел в сборке в Linux - PullRequest
7 голосов
/ 07 ноября 2011

Это должно быть сделано в чистой сборке (т. Е. Без библиотек или вызовов 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

Естьряд вопросов, подобных этому (а именно, , это и , это ), но я потерялся в реализации. Этот вопрос (для DOS) также был полезен, но я все еще в замешательстве.

Я должен что-то здесь упустить.Мысли?

Ответы [ 2 ]

5 голосов
/ 08 ноября 2011

Есть еще как минимум две проблемы. кроме коррупции ecx, о которой упоминал @sarnold:

  1. div ecx делит 64-битное значение edx:eax на ecx, поэтому необходимо убедиться, что вы установили edx в 0 до деления.

  2. Вторым аргументом системного вызова writeecx) должен быть указатель на буфер, содержащий символ, который вы хотите напечатать, а не сам символ.

Один из способов решения второй проблемы - поместить регистр, содержащий символ, который вы хотите напечатать, в стек, а затем назначить указатель стека esp на ecx (указатель стека указывает на последний добавленный элемент и x86 хранит значения с прямым порядком байтов, поэтому первый байт - младшие 8 бит). например, * * 1 022

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 голосов
/ 07 ноября 2011

Вы правильно установили 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.

...