正如标题说的那样,我正在做一个NASM项目:这个想法很简单,我需要从输入(string)中花一个月的时间,并给出天数(使用关于数字的案例)。直到现在,我花了一天的时间处理阅读/打印,最后比较了两条字符串。由于我在这里发现的一些老问题以及其他forums.My当前的问题,我可以这样做:我需要将月份(名称)放在数组中,以便与循环进行比较。我在另一个答案中看到,我可以这样标记“数组”: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 21hedit2:我尝试了@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文件,然后在dos中打开它。编辑:为了实现这个目标,我付出了很大的努力,即使我尝试了不同的方法,我也无法做到,最后一件事就是使用第一个月,并不断增加月份的大小,以传递给其他月份(即mon1+8给了我mon2 .)但是后来我遇到了尺寸上的差异,所以我把所有的月份都改成了3个字母(6月4个),这样我就可以用4的倍数移动,但是我不能一直走到最后。在那之后,我决定使用mon (I ),调用名称并重复操作,这似乎奏效了,我认为我在比较时遇到了一个问题(我仍在试图弄清楚),在我找到解决问题之前,这里是最后一个版本:即使我键入与mon1 to 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发布于 2020-01-11 20:27:01
试试这个:
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。
以下是你的问题尝试的细目:
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这一个使用一个不同的终止符,在这种情况下美元符号(24h = 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中断21h函数09h。此函数需要一个以美元结尾的字符串,因此只有您的12月字符串才能工作。更重要的是,它将尝试显示组成数组的文字字节。相反,您需要取消引用指向数组条目之一的指针,以加载存储在其中的地址,即关联消息字符串的地址。
https://stackoverflow.com/questions/59696958
复制相似问题