ассемблер linux распечатать все числа от нуля до 100

Я пишу программу для распечатки всех чисел от нуля до 100. Единственная причина, по которой я это делаю, это проверить распечатку многозначных чисел.

У меня проблема в том, что моя программа печатает только цифры 1 и 2. Я понятия не имею, почему. Мой компилятор компилируется нормально, без ошибок, а также без ошибок компоновщика.

Вот мой код:

SECTION .data
len EQU 32
NUL EQU 0
countlen EQU 8

SECTION .bss
counter resb countlen
strlen resb countlen

SECTION .text
GLOBAL _start
_start:
    mov BYTE[counter], 1              ; set counter to 1
    mov BYTE[strlen], 1               ; set string length counter to 1
    mov ecx, counter                  ; move the counter to ecx
    add BYTE[ecx], NUL                ; add null terminator to ecx
    mov esi, 9                        ; move 9 to esi

Length: 
    cmp [counter], esi                ; compare counter to esi
    jle Set                           ; if equal, goto set
    inc BYTE[strlen]                  ; increment the string size
    mov eax, 10                       ; move 10 to eax
    mov ebx, esi                      ; move esi to ebx
    mul ebx                           ; multiply ebx by esi
    add eax, 9                        ; add nine to the result
    mov esi, eax                      ; move the result to esi
    jmp Length                        ; jump to Length 

Set:
    mov esi, 9                        ; reset checker

Check:
    cmp BYTE[strlen], 1               ; is it one digit?
    je Single                         ; if yes, jump to single
    cmp BYTE[strlen], 3               ; is it 100?
    je Exit                           ; if yes, jump to Exit

Print:                                 ; this section deals with multi-digit numbers                                   
    cmp BYTE[ecx], NUL                ; check if end of string
    je Exit                           ; if equal goto exit 
    mov eax, 4
    mov ebx, 1
    mov edx, 1
    int 80h                           ; print number

    inc ecx                           ; point to next digit in number
    jmp Print                         ; jump to Print

Single:                                   ; this section deals with single digit numbers         add BYTE[counter], '0'            ; convert to ASCII
    mov eax, 4                       
    mov ebx, 1
    mov ecx, counter 
    mov edx, countlen 
    int 80h                           ; print the digit
    jmp Length                        ; go back

Exit:                                     ; Exit section
    mov eax, 1                        ; sys_exit
    mov ebx, 0                        ; return 0
    int 80h                           ; syscall

Почему он это делает? Кроме того, что мне нужно изменить, чтобы заставить его работать как положено?

Заранее спасибо,

RileyH

ОБНОВИТЬ:

Отредактировано, чтобы включить 'Распечатать' этикетка

 Serge27 окт. 2012 г., 08:41
и где находитсяPrint метка определена?

Ответы на вопрос(3)

ошибка" per se, но это просто неверное направление для случайного считывателя для доступа к счетчику и strlen как к одной байтовой переменной, а в других местах сравнивает содержимое с 32-битными переменными ...

add BYTE[ecx], NUL

это возможнодобавляет NUL терминатор вecx, но я полагаю, это должноприсоединять Терминатор. Это может произойти на месте.[ecx+1]

В любом случае, обработка переменных и указателей в вашем коде очень нетрадиционна ...

Во-первых: функции ядра, которые 'выход' материал, предположим, что ecx содержит адрес строки. Нетт строкавыделено в любом месте. Если строка будет вписываться в восемь байтов, зарезервированных для счетчика вcounter resb 8и счетчик будет содержать символы: ,,'1''3''\0' тогда подход будет работать. И это показывает второе: printf работает со строками, которые кодируют однозначные цифры 0-9 до значений 48-57. Например, пространство в этой системе ASCII кодируется до 32 (десятичного), в то время как \ NUL равно нулю.

Итак, что нужно:

Опция 1

Инициализируйте вашcounter в строку

counter db '0','0','0','0','0','0','0','1'  
length  dq 1

Ноль Ascii не нужен для завершения строки, потому что, как я понял, это 'дано функции печати

Тогда можно датьреальный указатель на строку как

lea ecx, counter     // get the address of counter string
add ecx, 7           // this is the last character

Также можно увеличить счетчик в виде строки по одной цифре за раз:

loop:  
mov al,[ecx]   // assuming ecx still points to last character  
inc al  
mov [ecx],al  
cmp al, '9'  
jle string ok  
mov al, '0'  
mov [ecx],al  
dec ecx  
jmp loop  
ok:     // here the counter has been increased correctly  

вариант 2

Увеличьте счетчик как 32-разрядное целое число. Преобразуйте целое число в строку по одной цифре за раз с помощью следующего алгоритма:

digits = 0;  
string_ptr = &my_string[32];  // move barely outside the string  
do {  
  last_digit = a % 10 + '0';      // calculate the last digit and convert to ASCII
  a = a / 10;  
  *--string_ptr = last_digit;     // write the last digit
  digits++;                       // count the number of digits  
} while (a);  
// because we predecrement string_ptr, that value also contains the exact  
// start of the first character in the printable string. And digits contains the length.

Чтобы получить хороший результат, нужно еще добавитьперевод строки, Это может быть обработано отдельно или простоприлагается к исходной строке - и убедитесь, что они никогда не будут перезаписаны, чтобы их можно было использовать во всех случаях.

 Frank Kotler27 окт. 2012 г., 18:40
Незначительная гнида: результатmul ebx идет вedx:eax - не надоне ожидалedx быть нетронутым!
 Aki Suihkonen27 окт. 2012 г., 10:18
mul ebx; не умножает esi на ebx. Неявный операнд MUL является eax, и результат переходит к eax. Также JLE не сравнивает равенство, но МЕНЬШЕ или РАВНО, что ОТО хорошо, потому что в противном случае я нене вижу быстрого выхода из цикла.

чтобы распечатать на терминале. Теперь я выигралЯ не дам тебе моего слова, это доставит удовольствие от обучения, но ты мог бы сделать что-то вроде этого:

sys_exit        equ     1
sys_write       equ     4
stdout          equ     1

SECTION .bss
lpBuffer    resb    4

SECTION .text
GLOBAL _start
_start:
    xor     esi, esi

.NextNum:
    call    PrintNum
    inc     esi
    cmp     esi, 100
    jna     .NextNum

.Exit:                                 
    mov     eax, sys_exit                
    xor     ebx, ebx                      
    int     80h                           

;~ #####################################################################
PrintNum:   
    push    lpBuffer
    push    esi 
    call    dwtoa

    mov     edi, lpBuffer
    call    GetStrlen
    inc     edx
    mov     ecx, lpBuffer

    mov     eax, sys_write
    mov     ebx, stdout
    int     80H     
    ret     

;~ #####################################################################    
GetStrlen:
    push    ebx
    xor     ecx, ecx
    not     ecx
    xor     eax, eax
    cld
    repne   scasb
    mov     byte [edi - 1], 10
    not     ecx
    pop     ebx
    lea     edx, [ecx - 1]
    ret

Заметьте, я использую такие вещи, как sys_exit, sys_write, stdout вместо жестко закодированных чисел. Делает код немного более самодокументированным.

 Progrmr30 окт. 2012 г., 06:12
Что вы имеете в виду ?dwtoa
 d33tah03 нояб. 2012 г., 12:20
Я думаю этоs имя функции - слово для ascii.
 Progrmr05 нояб. 2012 г., 11:32
Где я могу получить этоdwtoa функция от?

в AT &Извините;)

movl <your decimal="" here="">, %eax
xor %ecx, %ecx  # the counter
movl $10, %ebx  

loop:
xor %edx, %edx
div %ebx        # isolate the last digit, remainder in edx
add $48, %dx    # '0' is 48 in ascii, result is the ascii equivalent
shl $8, %dx     # move the ascii byte to %dh
pushw %dx       # puch ascii code on the stack
inc %esp        # point to the ascii byte! (discard %dl)
inc %ecx        # count the digits
cmp $0, %eax
jnz loop

movl $4, %eax     # write()
movl $1, %ebx     # stdout
movl %ecx, %edx   # now edx holds the number of digits
movl %esp, %ecx   # load the address of string array
int $0x80         # the string array is on top of the stack
</your>

Ура!

Ваш ответ на вопрос