getline 및 print_string "functions"가있는이 작은 experiement 부트 스트랩을 작성했습니다. 부트 물건은 MikeOS 튜토리얼에서 가져 왔지만 나머지는 나 자신을 썼다. 이것을 NASM으로 컴파일하고 QEMU에서 실행합니다.문자열 변수 지우기
실제 질문 : 저는이 변수 curInpLn을 6 행에 선언했습니다. 사용자 유형이 그 변수에 저장되고 입력 한 후에 사용자에게 몇 가지 추가 메시지가 표시됩니다. 내가하고 싶은 건 getline 함수가 호출 될 때마다 curInpLn의 내용을 지우는 것이지만, 어떤 이유로 그것을 할 수 없다. 나는 지금 Assmebly와 초보자입니다.
코드를 bin 형식으로 컴파일 한 다음 "dd status = noxfer conv = notrunc if if = FILENAME.bin"= "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
시도해 보았지만 작동하지 않는 것은 무엇입니까? BTW 자체적으로'di'는'ds'가 아니라'es'에 암묵적으로 접두사가 붙기 때문에 ('sp'와'bp'는'ss '를 사용합니다)'ds'와 동등하게'es'를 설정해야합니다. 또한, mov [bx] [di-1], 0은 mov 바이트 [bx + di-1], 0으로 기록 될 수있다. – user786653
안녕하세요! 바로 뒤에 : lea bx, [curInpLn] 나는 mov 바이트 {bx}, 0을 시도했고 그 전에 mov 바이트 [curInpLn], ''및 b) mov ax, 0 mov [curInpLn]을 시도했습니다. 도끼 –
나는 아직도 너를 정확히 따르지 않는다. 'curInpLn'에서 80 바이트를 모두 0으로 설정 하시겠습니까? 첫 번째 바이트를 0으로 설정하거나 완전히 다른 것으로 설정 하시겠습니까? 내가 코드를 읽었을 때마다 처음부터 시작하기 때문에 코드를 지울 필요가 없습니다. NUL (zero byte)로 문자열을 끝내고 싶습니까? (이 경우'.gtlDone :'다음에'mov byte [bx + di], 0'을하고'mov cx, 80'을'mov cx , 79' 반영)? – user786653