2011-08-31 3 views
0

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 
+0

시도해 보았지만 작동하지 않는 것은 무엇입니까? BTW 자체적으로'di'는'ds'가 아니라'es'에 암묵적으로 접두사가 붙기 때문에 ('sp'와'bp'는'ss '를 사용합니다)'ds'와 동등하게'es'를 설정해야합니다. 또한, mov [bx] [di-1], 0은 mov 바이트 [bx + di-1], 0으로 기록 될 수있다. – user786653

+0

안녕하세요! 바로 뒤에 : lea bx, [curInpLn] 나는 mov 바이트 {bx}, 0을 시도했고 그 전에 mov 바이트 [curInpLn], ''및 b) mov ax, 0 mov [curInpLn]을 시도했습니다. 도끼 –

+0

나는 아직도 너를 정확히 따르지 않는다. 'curInpLn'에서 80 바이트를 모두 0으로 설정 하시겠습니까? 첫 번째 바이트를 0으로 설정하거나 완전히 다른 것으로 설정 하시겠습니까? 내가 코드를 읽었을 때마다 처음부터 시작하기 때문에 코드를 지울 필요가 없습니다. NUL (zero byte)로 문자열을 끝내고 싶습니까? (이 경우'.gtlDone :'다음에'mov byte [bx + di], 0'을하고'mov cx, 80'을'mov cx , 79' 반영)? – user786653

답변

0

I (!)는 20 년 동안 국회에서 코드를 작성하지 않은,하지만 당신은 'stosw'명령 (또는 'stosb')를 사용할 필요 것 같습니다. STOSB는 ES : DI가 가리키는 바이트에 대해 AL에 보유 된 값을로드하지만 STOSSW는 AX에 보유 된 값을 012 :이라는 ES : DI가 가리키는 단어로로드합니다. 명령이 자동으로 포인터를 앞으로 이동합니다. 변수 curInpLn의 길이가 80 바이트이므로 STOSW를 40 회 반복하여 지울 수 있습니다.

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를 필요로하지 않는 변수를 삭제의 가장 빠른 방법입니다. 실제로 프리 페치 큐가 채워 지므로 다음 명령을 가능한 빨리 실행할 수 있습니다.

+0

노력을 감사하지만 "나는 수년 동안 x를하지 않았습니다 ..."로 시작하는 답변은 항상 도움이되는 것은 아닙니다. LODSx 명령어는 메모리에서 ax 레지스터로 데이터를로드합니다. 당신이 의미하는 바는 도끼에서 메모리까지의 가치를 저장하는 STOSx라고 생각합니다. – adelphus

+0

나는 ds : si와 lodsw 대신 es : di와 stosw를 사용하도록 코드를 수정했다. –