首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用NASM - Prototype定义字符串数组,给出一个月的天数。

使用NASM - Prototype定义字符串数组,给出一个月的天数。
EN

Stack Overflow用户
提问于 2020-01-11 17:36:11
回答 1查看 165关注 0票数 0

正如标题说的那样,我正在做一个NASM项目:这个想法很简单,我需要从输入(string)中花一个月的时间,并给出天数(使用关于数字的案例)。直到现在,我花了一天的时间处理阅读/打印,最后比较了两条字符串。由于我在这里发现的一些老问题以及其他forums.My当前的问题,我可以这样做:我需要将月份(名称)放在数组中,以便与循环进行比较。我在另一个答案中看到,我可以这样标记“数组”:label: db str1,str2我试过这样做,而当我尝试使用label打印时,仅在上个月(我尝试了label+i,但仍然得到了相同的东西)--好吧,下面是我代码的一部分:

代码语言:javascript
复制
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,下面是完整的代码:

代码语言:javascript
复制
     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文件,然后在dos中打开它。编辑:为了实现这个目标,我付出了很大的努力,即使我尝试了不同的方法,我也无法做到,最后一件事就是使用第一个月,并不断增加月份的大小,以传递给其他月份(即mon1+8给了我mon2 .)但是后来我遇到了尺寸上的差异,所以我把所有的月份都改成了3个字母(6月4个),这样我就可以用4的倍数移动,但是我不能一直走到最后。在那之后,我决定使用mon (I ),调用名称并重复操作,这似乎奏效了,我认为我在比较时遇到了一个问题(我仍在试图弄清楚),在我找到解决问题之前,这里是最后一个版本:即使我键入与mon1 to mon12不同的内容,也会得到这样的结果:Le mois de 'input' est de 30 jours,而通常情况下,它应该会带我回到nope标签的开头。

代码语言:javascript
复制
        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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-11 20:27:01

试试这个:

代码语言:javascript
复制
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作为硬编码数组长度。但是,对于更一般的静态数据数组来说,使用等价物来表示条目的长度和数量是有用的。

ETA:我为表添加了对齐,这对性能很好。不需要,但不贵。

请注意,我从示例中删除了org指令。这是因为我只介绍了一个应该从其他程序逻辑调用的函数。如果您要组装成一个简单风格的86-DOS平面.COM可执行文件,您仍然需要在某个时候包含org 256

以下是你的问题尝试的细目:

代码语言:javascript
复制
msg db "a"

这似乎是一个未使用的剩饭。

代码语言:javascript
复制
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代表零终止。)

代码语言:javascript
复制
mon12 db "decembre",24h

这一个使用一个不同的终止符,在这种情况下美元符号(24h = 36)。在数组条目之间混合终止符是不合适的。要么使用所有ASCIZ,要么使用所有CP/M样式的美元结束字符串。

代码语言:javascript
复制
mo dw 1,2,3,4,5,6,7,8,9,10,11,12

这是没用的。如果您想将一个从1到12的数字作为索引映射到这个数组中,那么将在该数组条目中找到原始值。如果条目有不同的编号,则这种类型的数组可能有用,但对于标识映射则不然。

代码语言:javascript
复制
mon:    
dw mon1,mon2,mon3,mon4,mon5,mon6,mon7,mon8,mon9,mon10,mon11,mon12

这在本质上是正确的。(我将每个条目放在自己的行上,并在“对齐”指令前面加上,但两者都不是绝对必要的。)

代码语言:javascript
复制
    mov dx,mon
    mov ah,09h             
    int 21h

这会将消息表的地址加载到dx中,然后通过dx中断21h函数09h。此函数需要一个以美元结尾的字符串,因此只有您的12月字符串才能工作。更重要的是,它将尝试显示组成数组的文字字节。相反,您需要取消引用指向数组条目之一的指针,以加载存储在其中的地址,即关联消息字符串的地址。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59696958

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档