Определите строковый массив с помощью NASM - Prototype даст количество дней в месяце - PullRequest
0 голосов
/ 11 января 2020

Ну, как говорится в названии, я работаю над проектом NASM: идея проста, мне нужно взять месяц от ввода (строка) и указать количество дней (с учетом случаев относительно чисел). До сих пор я провел день, занимаясь чтением / печатью и, наконец, сравнивая 2 строки, что я мог сделать после некоторых трудностей и благодаря некоторым старым вопросам, которые я нашел здесь и на других форумах. Моя текущая проблема заключается в том, что мне нужно поставить месяцев (имен) в массиве, чтобы я мог сделать сравнение с al oop, я увидел другой ответ, что могу пометить «массив» следующим образом: label: db str1,str2 Я пробовал это делать, и когда я пытался печатать только с помощью label Я получаю только последний месяц (я попробовал label + i, но я все еще получаю то же самое) Ну, вот часть моего кода:

segment .data
org 100h
msg db "a"
mon1 db "janvier",0
mon2 db "fevrier",0
mon3 db "mars",0
mon4 db "avril",0
mon5 db "mai",0
mon6 db "juin",0
mon7 db "juillet",0
mon8 db "aout",0
mon9 db "septembre",0
mon10 db "octobre",0
mon11 db "novembre",0
mon12 db "decembre",24h
mo dw 1,2,3,4,5,6,7,8,9,10,11,12
mon:    
dw mon1,mon2,mon3,mon4,mon5,mon6,mon7,mon8,mon9,mon10,mon11,mon12
segment .code
    mov dx,mon
    mov ah,09h             
    int 21h

edit2: я пробовал решение заданный @ecm, мне пришлось внести несколько изменений, потому что он дал мне несколько ошибок, после чего я смог, наконец, запустить его. Он перешел к error , вот весь код:

     segment .code
    display_month:
        ; takes month 1 to 12 in ax
        dec ax ; make number 0-based
        cmp ax,amount
        jae  error ; if out of range -->
        add ax, ax ; make it an index into a word array
        mov bx, ax ; use bx for addressing memory
        mov dx, word [mon+ bx] ; access array entry
        mov di, dx
        mov cx, -1
        mov al, 0
        repne scasb
        not cx
        dec cx ; string length
        mov bx, 1
        mov ah, 40h
        int 21h ; write to stdout
        clc ; indicate not error

        mov dx,msg1
        mov ah,09h
        int 21h
        mov ah,0Ah
        mov dx, len         ;start of buffer
        int 21h
        mov ah,02h
        mov dl,10
        int 21h
        mov dl,13
        int 21h     

        mov bx,act    
        mov dx,buffer 
        add dl,byte [bx]     
        mov bx,dx            ; move pointer into BX
        mov byte [bx],24h    ; put the $ there.

    ; compare input with msg variable(a placeholder for the moment ) I want to compare with the mon array values , and then use the index as an argument to call the cond procedure.
        mov ax,msg  
        mov si,ax
        mov ax,buffer
        mov di,ax
        cmpsb  
        jz Yep         ; if strings equal goto Yep
        jmp Nope       ; goto Nope


    Yep:
        mov dx,good
        mov ah,9
        int 21h    ; tell the user it's good
    Nope:
        mov dx,bad
        mov ah,9
        int 21h    ; tell the user it's bad
    end:
        mov  ah,4Ch
        int 21h
        ret
    error:
        stc
        retn
    cond:
        cmp ax,2
        je fev
        cmp ax,7
        jg odd
        jle even
    else:   mov bx,31
        jmp endif
    fev:    mov bx,28
    odd:    test ax,1
        jnz trente
        jmp else
    even:   test ax,1
        jp trente
        jmp else
    trente:  mov bx,30
    endif:  ret

    segment .data
    org 100h
        ;; variables declaration
    msg1 db "Veullez entrer un mois:",24h
    msg db "a",24h
    mon1:   db "janvier",0
    mon2:   db "fevrier",0
    mon3:   db "mars",0
    mon4:   db "avril",0
    mon5:   db "mai",0
    mon6:   db "juin",0
    mon7:   db "juillet",0
    mon8:   db "aout",0
    mon9:   db "septembre",0
    mon10:  db "octobre",0
    mon11:  db "novembre",0
    mon12:  db "decembre",0
    good db "Bon choix!",24h
    bad db "Mauvais choix!",24h
    mon:
     start:
        dw mon1,mon2,mon3,mon4,mon5,mon6,mon7,mon8,mon9,mon10,mon11,mon12
    tend:
    len db 254 ; a fair amount of space
    act db 0   ; will be filled with actual amount of chars received
    buffer times 254 db 0
    size equ  tend - start
    amount equ size / 2

Я забыл добавить, как я компилирую, я использую dosbox для запуска файлов .com, потому что они не работают на windows 10, и я использую команду: nasm name.asm -o name.com, чтобы создать файл .com, а затем Я просто открываю это в дос. РЕДАКТИРОВАТЬ: Ну, я изо всех сил пытался сделать это, я не мог этого сделать, даже подумал, что я пробовал разные способы, последнее, с чем я пошел, это использовать первый месяц и продолжать добавлять размер месяцев, чтобы передать другим (т.е. mon1 + 8 дает мне mon2 ...), но затем я столкнулся с разницей в размерах, поэтому я изменил все месяцы на всего 3 буквы (4 на июнь), чтобы я мог двигаться с кратными 4, но тогда я не мог t go до самого конца .. Итак после этого я просто решил использовать mon (i), называя имена и повторяя маневр, который, казалось, работал, хотя я столкнулся с проблемой с сравнивая (я все еще пытаюсь выяснить), вот последняя версия, пока я не выясню, как это исправить. Проблема на данный момент заключается в том, что даже если я наберу что-то отличное от mon1 до mon12, я получу это: Le mois de 'input' est de 30 jours в то время как обычно это возвращает меня к началу метки nope.

        segment .code
org 100h
    mov dx,msg1     
    mov ah,09h
    int 21h
here:   mov ah,0Ah  
    mov dx, len     
    int 21h
    mov ah,02h  
    mov dl,10
    int 21h
    mov dl,13
    int 21h     

    mov bx,act    
    mov dx,buffer
    add dl,byte [bx]     
    mov bx,dx            
    mov byte [bx],24h    
    jmp comp
yep:
    mov dx,g1       
    mov ah,09h
    int 21h
    mov dx,buffer
    int 21h
    mov dx,g2
    int 21h
    mov ax, [i]
    call cond       
    mov ah,02h
    mov dl,bh
    int 21h
    mov dl,bl
    int 21h
    mov dx,g3
    mov ah,09h
    int 21h
    jmp end
comp:   mov bx,0
    mov [i],bx

jan:    call inct   
    mov bx,buffer
    mov si,bx
    mov bx,mon1
    mov di,bx
        cmpsb
    jz yep

fevr:   call inct
    mov bx,buffer
    mov si,bx
    mov bx,mon2
    mov di,bx
    cmpsb
        jz yep

mar:    call inct
    mov bx,buffer
    mov si,bx
    mov bx,mon3
    mov di,bx
    cmpsb
    jz yep

avr:    call inct
    mov bx,buffer
    mov si,bx
    mov bx,mon4
    mov di,bx
    cmpsb
    jz yep

mai:    call inct
    mov bx,buffer
    mov si,bx   
    mov cx,mon5     
    mov di,cx
    cmpsb
    jz yep

juin:   call inct
    mov bx,buffer
    mov si,bx
    mov bx,mon6     
    mov di,bx
    cmpsb
    jz yep
    jmp jui

jui:    call inct
    mov cx,buffer
    mov si,cx
    mov cx,mon7
    mov di,cx
    cmpsb
    jz yep

aout:   call inct
    mov cx,buffer
    mov si,cx
    mov cx,mon8
    mov di,cx
    cmpsb
    jz yep
    jmp sep

sep:    call inct
    mov bx,buffer
    mov si,bx
    mov cx,mon9
    mov di,cx
    cmpsb
    jz yep
    jmp oct

oct:    call inct
    mov bx,buffer
    mov si,bx
    mov cx,mon10
    mov di,cx
    cmpsb
    jz yep
    jmp nov

nov:    call inct
    mov bx,buffer
    mov si,bx
    mov cx,mon11
    mov di,cx
    cmpsb
    jz yep
    jmp dect

dect:   call inct
    mov bx,buffer
    mov si,bx
    mov cx,mon12
    mov di,cx
    cmpsb
    jz yep
    jmp nope
nope:
    mov dx,bad      
    mov ah,9
    int 21h
    jmp here        
end:
    mov  ah,4Ch     
    int 21h         
    ret
inct:
    push bx
    mov bx,[i]
    inc bx
    mov [i],bx
    pop bx
    ret

cond:               
    cmp ax,2
    je fev
    cmp ax,6
    je th
    cmp ax,8
    je th
    cmp ax,7
    jg odd
    jle even
else:   mov bl,'1'
    mov bh,'3'
    jmp endif
fev:    mov bl, '8'
    mov bh,'2'
    jmp endif
th: jmp else
odd:    test ax,1
    jnz trente
    jmp else
even:   test ax,1
    jp trente
    jmp else
trente:  mov bh,'3'
     mov bl,'0'
endif:  ret


segment .data
i db 0
msg1 db "Veullez entrer un mois:",24h
mon1:   db "janvier",24h
mon2:   db "fevrier",24h
mon3:   db "mars",24h
mon4:   db "avril",24h
mon5:   db "mai",24h
mon6:   db "juin",24h
mon7:   db "juillet",24h
mon8:   db "aout",24h
mon9:   db "septembre",24h
mon10:  db "octobre",24h    
mon11:  db "novembre",24h
mon12:  db "decembre",24h
g1 db "Le mois de",20h,24h
g2 db 20h,"est de",20h,24h
g3 db 20h,"jours",24h
bad db "Le mois saisi  n'est pas correct!",10,13,"Veuillez entrer un autre mois:",24h
len db 254 ; a fair amount of space
act db 0   ; will be filled with actual amount of chars received
buffer times 254 db 0

1 Ответ

2 голосов
/ 11 января 2020

Попробуйте:

segment .code
display_month:
    ; takes month 1 to 12 in ax
    dec ax ; make number 0-based
    cmp ax, montab.amount
    jae .error ; if out of range -->
    add ax, ax ; make it an index into a word array
    mov bx, ax ; use bx for addressing memory
    mov dx, word [montab + bx] ; access array entry
    mov di, dx
    mov cx, -1
    mov al, 0
    repne scasb
    not cx
    dec cx ; string length
    mov bx, 1
    mov ah, 40h
    int 21h ; write to stdout
    clc ; indicate not error
    retn

.error:
    stc
    retn

segment .data
mon1: db "janvier",0
mon2: db "fevrier",0
mon3: db "mars",0
mon4: db "avril",0
mon5: db "mai",0
mon6: db "juin",0
mon7: db "juillet",0
mon8: db "aout",0
mon9: db "septembre",0
mon10: db "octobre",0
mon11: db "novembre",0
mon12: db "decembre",0

    align 2
montab:
.:
    dw mon1
    dw mon2
    dw mon3
    dw mon4
    dw mon5
    dw mon6
    dw mon7
    dw mon8
    dw mon9
    dw mon10
    dw mon11
    dw mon12
.end:
.size equ .end - .
.amount equ .size / 2

В этом случае вы можете использовать 12 в качестве длины массива с жестким кодом. Но использование equates для длины и количества записей полезно для stati c массивов данных в целом.

ETA : я добавил выравнивание для таблицы, что хорошо для производительности. Не требуется, но это не стоит больших затрат.

Обратите внимание, что я исключил директиву org из моего примера. Это потому, что я представляю только одну функцию, которая должна вызываться из другой программы logi c. Если вы собираете в простой плоский стиль исполняемый файл .COM для 86-DOS, вам все равно нужно в какой-то момент включить org 256.


Вот разбивка попытки вашего вопроса:

msg db "a"

Это похоже на неиспользованный остаток.

mon1 db "janvier",0
mon2 db "fevrier",0
mon3 db "mars",0
mon4 db "avril",0
mon5 db "mai",0
mon6 db "juin",0
mon7 db "juillet",0
mon8 db "aout",0
mon9 db "septembre",0
mon10 db "octobre",0
mon11 db "novembre",0

Все в порядке, они определяют строки ASCIZ. (Z обозначает нулевой терминатор.)

mon12 db "decembre",24h

Этот использует другой терминатор, в данном случае знак доллара (24 часа = 36). Нельзя смешивать терминаторы между записями массива. Либо используйте все строки ASCIZ или все строки в стиле CP / M, оканчивающиеся на доллар.

mo dw 1,2,3,4,5,6,7,8,9,10,11,12

Это бесполезно. Если вы хотите отобразить число от 1 до 12 в качестве индекса в этот массив, исходное значение будет найдено в этой записи массива. Если записи имеют разные номера, этот тип массива может быть полезен, но не с отображением идентификаторов.

mon:    
dw mon1,mon2,mon3,mon4,mon5,mon6,mon7,mon8,mon9,mon10,mon11,mon12

Это по существу правильно. (Я помещаю каждую запись в отдельной строке и добавляю к ней директиву выравнивания, но ни одна из них не является абсолютно необходимой.)

    mov dx,mon
    mov ah,09h             
    int 21h

Это загружает адрес вашей таблицы сообщений в dx, затем передает dx для прерывания. 21 ч. Функция 09 ч. Эта функция ожидает строку, оканчивающуюся долларом, поэтому будет работать только ваша декабрьская строка. Что еще более важно, он будет пытаться отобразить буквенные байты, которые составляют ваш массив. Вместо этого вам нужно разыменовать указатель на одну из записей вашего массива, чтобы загрузить сохраненный в нем адрес, который является адресом соответствующей строки сообщения.

...