2016-06-09 5 views
1

Новое для сборки .. это код. он считывает последовательность символов и заканчивается, когда вы нажимаете enterкак закончить входную последовательность символов: ASM: Int 21h функция 01h

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

и что AL в CMP представляют, и почему 0DH? я путаюсь в этой строке (CMP AL,0DH)

MAIN PROC 

;INITIALIZE DS 
MOV AX,@DATA  
MOV DS,AX 

MOV  DI,1000H 
MOV  AH,01H 
LOOP: 
INT  21H 
CMP  AL,0DH 
JE  END 
MOV  [DI],AL 
INC  DI 
JMP  LOOP 

END: 
MOV AH,4CH   ;DOS EXIT FUNCTION 
INT 21H   ;EXECUTE 

MAIN ENDP 
END MAIN 
+0

Я думаю, что вы используете функцию чтения-символа DOS, поэтому просто считайте счетчик циклов до 20 или от 20 до 0 в качестве условия выхода из цикла. 'cmp al, 0dH' сравнивает символ, который вы только что прочитали, чтобы увидеть, является ли это' \ r'. (DOS 'ah = 1/int 21' возвращает символ в регистре' al'). Подробнее см. [Wiki для x86] (http://stackoverflow.com/tags/x86/info). –

+0

Как я собираюсь сделать это _ ", так просто посчитайте счетчик циклов до 20 или ниже от 20 до 0 в качестве условия цикла-выхода" _ sir @PeterCordes – Vadamadafaka

+0

Каждая итерация цикла получает один символ, не так ли? Поэтому вместо бесконечного цикла сделайте цикл, в котором выполняется не более 20 итераций. например 'mov cx, 20' вне цикла. Затем используйте 'dec cx/jnz LOOP' вместо' jmp LOOP'. Какие другие языки программирования вы знаете? Подумайте о том, что должно произойти, прежде чем вы столкнетесь с подробностями о каждом шаге в asm. –

ответ

3

ВРП читает символы один за другим, сохраняя его на Адресс 1000 и далее. он явно не заботится о длине ввода и останавливается, как только считывается 0x0d (это символ новой строки, поэтому он читает до нажатия нажатия)

(Я заменил «mov [di], al« + »inc di "с„STOSB“, который делает точно то же самое)

добавить„чек максимальная длина“, вы могли бы сделать что-то вроде этого внутри цикла:

mov ax, DI 
sub ax, 0x1000 
cmp ax, <the max length you want to read> 
jae END 

Примечание: ввода не сохраняется, поэтому, если вы измените SI (который в настоящее время указывает на последний введенный символ), возникнет проблема с определением конца строки. Лучше Хранить 0x0d слишком (или даже лучше 0x00), чтобы иметь конца-строки маркера:

MAIN PROC 

;INITIALIZE DS 
MOV AX,@DATA  
MOV DS,AX 
cld     ; tell "stosb" to forward 

MOV  DI,1000H ; address where to string will be copied to 
MOV  AH,01H  ; int 21 function 1: read char with echo 
LOOP: 
    INT  21H   ; read a char from keyboard 
    stosb    ; store char in string 
    CMP  AL,0DH  ; stop if enter is pressed (after storing, so 0x0d will be stored too) 
JNE  LOOP 

END: 
MOV AH,4CH   ;DOS EXIT FUNCTION 
INT 21H   ;EXECUTE 

MAIN ENDP 

или хранящий 0х00 и входной конец в:

MAIN PROC 

;INITIALIZE DS 
MOV AX,@DATA  
MOV DS,AX 
cld     ; tell "stosb" to forward 

MOV  DI,1000H ; address where to string will be copied to 
MOV  AH,01H  ; int 21 function 1: read char with echo 
LOOP: 
    INT  21H   ; read a char from keyboard 
    CMP  AL,0DH  ; stop if enter is pressed 
    JE  END 
    stosb    ; save al at DI and increase DI by one 
JMP  LOOP 

END: 
mov [di], 0   ; terminate string (instead of 0x0d) 
MOV AH,4CH   ;DOS EXIT FUNCTION 
INT 21H   ;EXECUTE 

MAIN ENDP 

Еще одна идея о «Ограничить количество прочитанных символов» (вместо проверки DI для 0x1000 + 20, чтобы выскочить из цикла чтения) было бы использовать CX в качестве счетчика и loop (цикл - это условный переход, который уменьшает CX и скачки, если CX didn ' t достигают 0):

MAIN PROC 

;INITIALIZE DS 
MOV AX,@DATA  
MOV DS,AX 
cld     ; tell "stosb" to forward 

mov  cx, 20  ; make sure to maximum read 20 chars 
MOV  DI,1000H ; address where to string will be copied to 
MOV  AH,01H  ; int 21 function 1: read char with echo 
LOOP: 
    INT  21H   ; read a char from keyboard 
    CMP  AL,0DH  ; stop if enter is pressed 
    JE  END 
    stosb    ; save al at DI and increase DI by one 
loop  LOOP 

END: 
mov [di], 0   ; terminate string (instead of 0x0d) 
MOV AH,4CH   ;DOS EXIT FUNCTION 
INT 21H   ;EXECUTE 

MAIN ENDP 
+0

, но последовательность входных символов не имеет ограничений при вводе, как ограничить введенные символы? например, я могу набирать только 20 символов, и программа закончится? – Vadamadafaka

+1

Как правило, вы не просто записываете строку «где-то» (например, здесь до 0x1000), но вы определяете для нее буфер. как ограничить чтение, написано в ответе – Tommylee2k

+0

'stosb' не ясно« лучше », если вы не оптимизируете размер кода. Специально для новичка, учащегося перемещать указатели вокруг и разыгрывать их, общий путь - хорошая идея. (по производительности: 'stos' - это 3 uops на семействе SnB и, по-видимому, не может скомпоновать файлы store-address и store-data uops.' inc' - 1 uop и 'mov [di], al' также является 1 мкп (микроконтейнерный адрес магазина и данные хранилища).) –