清除字符串变量

时间:2011-08-31 14:11:31

标签: string variables assembly nasm

我已经写了这个带有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

1 个答案:

答案 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从预取队列中检索任何指令。实际上,它允许预取队列填满,从而允许任何后续指令尽快执行。