清除字符串变量

发布于 2024-12-02 02:15:21 字数 3408 浏览 0 评论 0原文

我写了这个小实验引导程序,它有一个 getline 和 print_string “函数”。引导内容取自 MikeOS 教程,但其余部分是我自己编写的。我使用 NASM 编译它并在 QEMU 中运行它。

所以实际的问题是:我在第 6 行声明了这个变量 curInpLn。用户输入的任何内容都会保存在该变量上,然后在按下 Enter 键后,它会向用户显示一些附加消息。我想做的是每次调用 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

I have writen this little experiement bootstrap that has a getline and print_string "functions". The boot stuff is taken from MikeOS tutorial but the rest I have writen myself. I compile this with NASM and run it in QEMU.

So the actual question: I've declared this variable curInpLn on line 6. What ever the user types is saved on that variable and then after enter is hit it is displayed to the user with some additional messages. What I'd like to do is to clear the contents of curInpLn each time the getline function is called but for some reason I can't manage to do that. I'm quite the beginner with Assmebly at the moment.

You can compile the code to bin format and then create a floppy image of it with: "dd status=noxfer conv=notrunc if=FILENAME.bin of=FILENAME.flp" and run it in qemu with: "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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一生独一 2024-12-09 02:15:21

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

I haven't written code in Assembly for 20 years (!), but it looks like you need to use the 'stosw' instruction (or 'stosb'). STOSB loads the value held in AL to the byte pointed to by ES:DI, whereas STOSSW loads the value held in AX to the word pointed to by ES:DI. The instruction automatically advances the pointer. As your variable curInpLn is 80 bytes long, you can clear it with 40 iterations of STOSW. Something like

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

This method is probably the quickest method of clearing the variable as it doesn't require the CPU to retrieve any instructions from the pre-fetch queue. In fact, it allows the pre-fetch queue to fill up, thus allowing any following instructions to execute as quickly as possible.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文