Печать от 1 до <пользовательский ввод в emu8086 - PullRequest
1 голос
/ 03 апреля 2019

Я хочу получить число (т. Е. 5) от пользователя, а затем распечатать, начиная с 1 до

Я знаю, что цикл запускается CX раз, и, как в 8086, MOVZX не ​​работает, поэтому сначала я переместил AL в CL, а затем обнулил CH.

Как кто-то упомянул, что проблемакогда я перемещаю AL в CX, я не перемещаю значение 4, я перемещаю 34 (значение ASCII 4), и поэтому мой цикл выполняется 34 раза.

Теперь, как мне преобразовать мое пользовательское значение вводав десятичный и переместить это в CX.Есть ли способ принять пользовательский ввод, который будет храниться в AL в качестве десятичного значения?

org 100h




MOV AH, 1  ; Get user input 
INT 21H


DEC AL ; Dec AL to satisfy the condition that it will print till < input

MOV BL,31H ; Initialize BL so that the output starts printing from 1 

MOV CL,Al ; set counter register CX 
MOV CH,00


Print:

MOV AH, 2    ; for output printing
MOV DL,0DH  ; for output printing
INT 21H      ; for output printing

MOV DL,0AH      ; for output printing
INT 21H            ; for output printing

MOV AH,2
MOV DL,BL         ; print what is in BL 
INT 21H

INC BL             ; then increment BL

LOOP Print     ; supposed to run the loop on Print what is the value in CL times

hlt

Ответы [ 2 ]

3 голосов
/ 03 апреля 2019
MOV AH, 1  ; Get user input 
INT 21H

Если вы введете 5 , то регистр AL будет содержать число 35h, которое является кодом ASCII этой клавиши. Вы явно хотите, чтобы этот ключ представлял собой 5. Вы должны вычесть 30 часов (48).

mov     ah, 01h  ; DOS.GetKey 
int     21h
sub     al, '0'
dec     al
mov     cl, al
mov     ch, 0

Остальная часть программы подходит для печати, начиная с 1 до

1 голос
/ 03 апреля 2019

Теперь, как мне преобразовать введенное пользователем значение в десятичное и переместить его в CX.

Вы попали в ловушку забывания условий цикла, отличных от *Возможно 1006 *, с использованием инструкций, отличных от loop.

loop - это просто оптимизация глазка для dec cx / jnz (без влияния на FLAGS).Используйте его только тогда, когда это самый эффективный способ зацикливания.(Или просто никогда не используйте его вообще, потому что вам все равно нужно понимать условные переходы, поэтому пропуская loop - это на одну инструкцию меньше, чтобы узнать / запомнить. Кроме того, на большинстве современных процессоров x86, loop намного медленнее, чемdec / jnz . Это хорошо, если вы настраиваете на реальный 8086 или оптимизируете для увеличения размера кода, хотя. Но необходимо только в качестве оптимизации .


Самый простой и логически понятный способ написания этого цикла:

    MOV AH, 1     ; read a char from stdin into AL
    INT 21H

    mov   cl, al    ; ending character
    mov   bl, '1'   ; b = current character, starting with '1'

.top:                  ; do {

    ... print CR/LF   (not shown)

    mov   dl, bl
    int   21h            ; With AH=2 from printing CR/LF

    inc   bl             ; b++
    cmp   bl, cl
    jbe  .top          ; }while(b <= end_char);

Обратите внимание, что я увеличиваю после печати. ​​Если вы увеличиваете до печати, вы будете использовать jb для }while(b < end_char).


На реальном 8086, где эффективен loop, он имеет больше инструкций и больше байтов кода внутри цикла, и, следовательно, может быть медленнее (если мы рассмотримслучай, когда издержки цикла имеют значение, а не 3х медленных системных вызовов int 21h внутри цикла).

Но это идет вразрез с меньшим общим размером кода (из тривиальной настройки цикла). Так что это компромисс между статическимикодразмер против динамического числа команд (и количество байтов кода, которые необходимо извлечь, что было настоящей проблемой на 8086).

...