我已經寫了一個有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