我已经写了这个带有getline和print_string“functions”的小体验引导程序。引导的东西取自MikeOS教程,但其余的我自己写了。我用NASM编译它并在QEMU中运行它。
所以实际的问题是:我已经在第6行声明了这个变量curInpLn。用户输入的内容在该变量上保存了什么,然后在输入命中后,它会向用户显示一些其他消息。我想做的是每次调用getline函数时清除curInpLn的内容但由于某种原因我无法做到这一点。我现在是Assmebly的初学者。
您可以将代码编译为bin格式,然后使用以下命令创建它的软盘映像:“dd status = noxfer conv = notrunc if = FILENAME.bin of = FILENAME.flp”并在qemu中运行:“qemu - fda FILENAME.flp“
BITS 16
jmp start
welcomeSTR: db 'Welcome!',0
promptSTR: db 'Please prompt something: ',0
responseSTR: db 'You prompted: ',0
curInpLn: times 80 db 0 ;this is a variable to hold the input 'command'
curCharCnt: dw 0
curLnNum: dw 1
start:
mov ax, 07C0h ; Set up 4K stack space after this bootloader
add ax, 288 ; (4096 + 512) / 16 bytes per paragraph
mov ss, ax
mov sp, 4096
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
call clear_screen
lea bx, [welcomeSTR] ; Put string position into SI
call print_string
call new_line
.waitCMD:
lea bx, [promptSTR]
call print_string
call getLine ; Call our string-printing routine
jmp .waitCMD
getLine:
cld
mov cx, 80 ;number of loops for loopne
mov di, 0 ;offset to bx
lea bx, [curInpLn] ;the address of our string
.gtlLoop:
mov ah, 00h ;This is an bios interrupt to
int 16h ;wait for a keypress and save it to al
cmp al, 08h ;see if backspace was pressed
je .gtlRemChar ;if so, jump
mov [bx+di], al ;effective address of our curInpLn string
inc di ;is saved in bx, di is an offset where we will
;insert our char in al
cmp al, 0Dh ;see if character typed is car-return (enter)
je .gtlDone ;if so, jump
mov ah, 0Eh ;bios interrupt to show the char in al
int 10h
.gtlCont:
loopne .gtlLoop ;loopne loops until cx is zero
jmp .gtlDone
.gtlRemChar:
;mov [bx][di-1], 0 ;this needs to be solved. NASM gives error on this.
dec di
jmp .gtlCont
.gtlDone:
call new_line
lea bx, [responseSTR]
call print_string
mov [curCharCnt], di ;save the amount of chars entered to a var
lea bx, [curInpLn]
call print_string
call new_line
ret
print_string: ; Routine: output string in SI to screen
mov si, bx
mov ah, 0Eh ; int 10h 'print char' function
.repeat:
lodsb ; Get character from string
cmp al, 0
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
jmp .repeat
.done:
ret
new_line:
mov ax, [curLnNum]
inc ax
mov [curLnNum], ax
mov ah, 02h
mov dl, 0
mov dh, [curLnNum]
int 10h
ret
clear_screen:
push ax
mov ax, 3
int 10h
pop ax
ret
times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s
dw 0xAA55 ; The standard PC boot signature
答案 0 :(得分:1)
我没有在Assembly中编写代码20年(!),但看起来你需要使用'stosw'指令(或'stosb')。 STOSB将AL中保存的值加载到ES:DI指向的字节,而STOSSW将AX中保存的值加载到ES:DI指向的字。该指令自动使指针前进。由于变量curInpLn长度为80个字节,因此可以使用40次STOSW迭代清除它。像
这样的东西xor ax, ax ; ax = 0
mov es, ds ; point es to our data segment
mov di, offset curInpLn ; point di at the variable
mov cx, 40 ; how many repetitions
rep stosw ; zap the variable
此方法可能是清除变量的最快方法,因为它不需要CPU从预取队列中检索任何指令。实际上,它允许预取队列填满,从而允许任何后续指令尽快执行。