Очистка строковой переменной - PullRequest
0 голосов
/ 31 августа 2011

Я написал этот маленький экспериментальный загрузчик, который имеет функции getline и print_string.Загрузочный материал взят из учебника MikeOS, но остальное я написал сам.Я компилирую это с помощью NASM и запускаю в QEMU.

Итак, актуальный вопрос: я объявил эту переменную curInpLn в строке 6. Что бы пользовательские типы не сохранялись в этой переменной, а затем после ввода нажималотображается пользователю с некоторыми дополнительными сообщениями.Я хотел бы очистить содержимое curInpLn каждый раз, когда вызывается функция getline, но по какой-то причине мне не удается это сделать.Я довольно новичок в 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 Ответ

1 голос
/ 07 февраля 2012

Я не писал код на ассемблере уже 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

Этот метод, вероятно, является самым быстрым методом очистки переменной, поскольку он не требует от ЦП извлечения каких-либо инструкций из очереди предварительной выборки.Фактически, он позволяет заполнить очередь предварительной выборки, что позволяет выполнять следующие инструкции как можно быстрее.

...