我已经写了一个有getline和print_string“functions”的小实验引导程序。引导的东西取自MikeOS教程,但其余的我写了自己。我用NASM编译并在QEMU中运行它。清除字符串变量
所以真正的问题:我已经在第6行声明了这个变量curInpLn。用户类型被保存在该变量中,然后在输入命中后,它会向用户显示一些额外的消息。我想要做的是在每次调用getline函数时清除curInpLn的内容,但出于某种原因,我无法做到这一点。我现在非常适合初学者。
您可以将代码编译为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
你有什么试过,不起作用?顺便说一句,你应该设置'es'等于'ds',因为'di'本身隐含地以'es'为前缀,而不是'ds'(如'sp'和'bp'使用'ss')。另外'mov [bx] [di-1],0'可以写为'mov byte [bx + di-1],0'。 – user786653
嗨!之后:lea bx,[curInpLn]我试过a)mov byte [bx],0,就在它之前我试过了a)mov byte [curInpLn],''和b)mov ax,0 mov [curInpLn],斧 –
恐怕我还没有跟着你。你是否想要'curInpLn'中的所有80个字节设置为零,你只是想将第一个字节设置为零或完全是其他的吗?当我读取你的代码时,你不需要清除它,因为无论如何你每次都从头开始。你只是希望NUL(零字节)终止字符串(在这种情况下,只需在'.gtlDone:'之后执行'mov byte [bx + di],0',并且可能将'mov cx,80'改为mov cx ,79'来反映它)? – user786653