宏跳转异常

闭才 2016-03-24 04:46:36
编译环境VS2015
照着书写了个实现队列的小程序 (源程序见后面),出问题的可能是这个宏

enqueue macro
.if count < lengthof queue
inc count
mov eax, number
mov [edi], eax
mov eax, edi
sub eax, offset queue
add eax, 4
cdq
mov ecx, sizeof queue
idiv ecx
mov edi, offset queue
add edi, edx
.else
INVOKE printf, ADDR errfmt, ADDR errmsg2
.endif
endm

调试的时候,VS报

我反汇编了下 看到了奇怪的东西 what 6803113F 怎么会跑到这么个奇怪的地方 这什么也没有啊
  
69: enqueue
0003106C 83 3D C3 30 03 00 03 cmp dword ptr [count (0330C3h)],3
00031073 7D 2A jge @C0002+60h (03109Fh)
70: .elseif command=="d"
00031075 FF 05 C3 30 03 00 inc dword ptr [count (0330C3h)]
0003107B A1 BF 30 03 00 mov eax,dword ptr [number (0330BFh)]
00031080 89 07 mov dword ptr [edi],eax
00031082 8B C7 mov eax,edi
00031084 2D AF 30 03 00 sub eax,offset queue (0330AFh)
00031089 83 C0 04 add eax,4
0003108C 99 cdq
0003108D B9 0C 00 00 00 mov ecx,0Ch
00031092 F7 F9 idiv eax,ecx
00031094 BF AF 30 03 00 mov edi,offset queue (0330AFh)
00031099 03 FA add edi,edx
69: enqueue
0003109B E9 9F 00 00 68 jmp 6803113F

看另外一个宏 @C0002+119h (031158h) 这才正常嘛

71: dequeue
000310BF 83 3D C3 30 03 00 00 cmp dword ptr [count (0330C3h)],0
000310C6 7E 27 jle @C0002+0B0h (0310EFh)
72: .if number > 0
000310C8 FF 0D C3 30 03 00 dec dword ptr [count (0330C3h)]
000310CE 8B 06 mov eax,dword ptr [esi]
000310D0 A3 BF 30 03 00 mov dword ptr [number (0330BFh)],eax
000310D5 8B C6 mov eax,esi
000310D7 2D AF 30 03 00 sub eax,offset queue (0330AFh)
000310DC 83 C0 04 add eax,4
000310DF 99 cdq
000310E0 B9 0C 00 00 00 mov ecx,0Ch
000310E5 F7 F9 idiv eax,ecx
000310E7 BE AF 30 03 00 mov esi,offset queue (0330AFh)
000310EC 03 F2 add esi,edx
71: dequeue
000310EE EB 68 jmp @C0002+119h (031158h)

于是我困惑了 第一个宏怎么就会跳那么远啊 刚开始学汇编 没什么思路 求指点

源代码:
			
.listall
.386
.model flat, c
.stack 100h
scanf PROTO arg2: Ptr Byte, inputlist: VARARG
printf PROTO arg1: Ptr Byte, printflist: VARARG
.data
in1fmt byte "%s", 0
in2fmt byte "%d", 0
msg1fmt byte 0Ah, "%s", 0
msg3fmt byte 0Ah, "%s%d", 0Ah, 0
msg4fmt byte 0Ah, 0
errfmt byte 0Ah, "%s", 0Ah, 0
msg1 byte "Enter a command, e, d, or s: ", 0
msg2 byte "Enter a positive integer: ", 0
msg3 byte "Te integerr is : ", 0
errmsg1 byte "Error: Invalid entry, try again", 0
errmsg2 byte "Error: Queue is full", 0
errmsg3 byte "Error: Queue is empty", 0
queue sdword 3 dup(7)
command sdword ?
number sdword ?
count sdword 0
.code
enqueue macro
.if count < lengthof queue
inc count
mov eax, number
mov [edi], eax
mov eax, edi
sub eax, offset queue
add eax, 4
cdq
mov ecx, sizeof queue
idiv ecx
mov edi, offset queue
add edi, edx
.else
INVOKE printf, ADDR errfmt, ADDR errmsg2
.endif
endm
dequeue macro
.if count > 0
dec count
mov eax, [esi]
mov number, eax
mov eax, esi
sub eax, offset queue
add eax, 4
cdq
mov ecx, sizeof queue
idiv ecx
mov esi, offset queue
add esi, edx
.else
INVOKE printf, ADDR errfmt, ADDR errmsg3
mov number, -1
.endif
endm
main proc
mov edi, offset queue + 0
mov esi, offset queue + 0
INVOKE printf, ADDR msg1fmt, ADDR msg1
INVOKE scanf, ADDR in1fmt, ADDR command
.while command != "s"
.if command == "e"
INVOKE printf, ADDR msg1fmt, ADDR msg2
INVOKE scanf, ADDR in2fmt, ADDR number
enqueue
.elseif command=="d"
dequeue
.if number > 0
INVOKE printf, ADDR msg3fmt, ADDR msg3, number
.endif
.else
INVOKE printf, ADDR errfmt, ADDR errmsg1
.endif
INVOKE printf, ADDR msg1fmt, ADDR msg1
INVOKE scanf, ADDR in1fmt, ADDR command
.endw
INVOKE printf, ADDR msg4fmt
ret
main endp
end

...全文
198 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
闭才 2016-03-25
  • 打赏
  • 举报
回复
对了楼主后面又遇到各种问题 一怒之下就不用高级汇编指令 不用宏了 然后就好了 献上源码供参考 楼主推测是高级汇编指令的问题

.listall
            .386
            .model    flat, c
            .stack    1000h
scanf       PROTO     arg2: Ptr Byte, inputlist: VARARG
printf      PROTO    arg1: Ptr Byte, printflist: VARARG
            .data
in1fmt      byte    "%s", 0
in2fmt      byte    "%d", 0
msg1fmt     byte    0Ah, "%s", 0
msg3fmt     byte    0Ah, "%s%d", 0Ah, 0
msg4fmt     byte    0Ah, 0
errfmt      byte    0Ah, "%s", 0Ah, 0
msg1        byte    "Enter a command, e, d, or s: ", 0
msg2        byte    "Enter a positive integer: ", 0
msg3        byte    "Te integerr is : ", 0
errmsg1     byte    "Error: Invalid  entry, try again", 0
errmsg2     byte    "Error: Queue is full", 0
errmsg3     byte    "Error: Queue is empty", 0
queue       sdword  3 dup(7)
command     sdword  ? 
number      sdword  0
count       sdword  0
            .code

main        proc
            mov     edi, offset queue + 0
            mov     esi, offset queue + 0
            INVOKE  printf, ADDR msg1fmt, ADDR msg1
            INVOKE  scanf, ADDR in1fmt, ADDR command
while01:    cmp     command, "s"
            je		endw01
if01:       cmp     command, "e"
            jne     else01 
then01:     INVOKE  printf, ADDR msg1fmt, ADDR msg2
            INVOKE  scanf, ADDR in2fmt, ADDR number
if05:		cmp     count,lengthof queue
			jge     else05
then05:		inc     count
			mov     eax, number
			mov    [edi], eax
			mov     eax, edi
			sub     eax, offset queue
			add     eax, 4
			cdq
			mov     ecx, sizeof queue
			idiv    ecx
			mov     edi, offset queue
			add     edi, edx
            jmp     endif05
else05:     INVOKE  printf, ADDR errfmt, ADDR errmsg2
endif05:    nop
			jmp		endif01
else01:     nop
if02:       cmp		command, "d" 
			jne		else02
then02:     nop
if04 :		cmp     count, 0
			jle     else04
then04 :    nop
			dec     count
			mov     eax, [esi]
			mov     number, eax
			mov     eax, esi
			sub     eax, offset queue
			add     eax, 4
			cdq
			mov     ecx, sizeof queue
			idiv    ecx
			mov     esi, offset queue
			add     esi, edx
			jmp     endif04
else04 :    INVOKE  printf, ADDR errfmt, ADDR errmsg3
			mov     number, -1
endif04 :   nop
if03:       cmp		number, 0
            jle		endif02
then03:		INVOKE    printf, ADDR msg3fmt, ADDR msg3, number
            jmp		endif02
endif03:    nop
else02:     INVOKE  printf, ADDR errfmt, ADDR errmsg1
endif02:    nop
endif01 :   nop
            INVOKE  printf, ADDR msg1fmt, ADDR msg1
            INVOKE  scanf, ADDR in1fmt, ADDR command

            jmp     while01
endw01:     nop
            INVOKE  printf, ADDR msg4fmt
            ret
main        endp
            end
                   
fornetuse123 2016-03-25
  • 打赏
  • 举报
回复
引用 10 楼 BiCai2 的回复:
新的问题是这样的 [quote=引用 7 楼 fornetuse123 的回复:] sub eax, offset queue add eax, 4 cdq mov ecx, sizeof queue idiv ecx 这段真看不明白,直接 mov exa, count cdq idiv ecx 不就行了吗,eax取基址偏移,然后+4这是在干吗
n在这里是队列长度,idiv n肯定是有问题的。 +4是因为sdword型长度就是4字节啊 4表示有一个数啊 因为是从0开始的 所以 地址偏移长度与实际队列长度差1*4 在前面加和在后面加都可以吧[/quote] 好像明白了,它是用以前队列偏移+字节数=当前队列偏移。嗯还是这样算偏移正确。
闭才 2016-03-25
  • 打赏
  • 举报
回复
新的问题是这样的
引用 7 楼 fornetuse123 的回复:
sub eax, offset queue add eax, 4 cdq mov ecx, sizeof queue idiv ecx 这段真看不明白,直接 mov exa, count cdq idiv ecx 不就行了吗,eax取基址偏移,然后+4这是在干吗
n在这里是队列长度,idiv n肯定是有问题的。 +4是因为sdword型长度就是4字节啊 4表示有一个数啊 因为是从0开始的 所以 地址偏移长度与实际队列长度差1*4 在前面加和在后面加都可以吧
fornetuse123 2016-03-25
  • 打赏
  • 举报
回复
引用 7 楼 fornetuse123 的回复:
sub eax, offset queue add eax, 4 cdq mov ecx, sizeof queue idiv ecx 这段真看不明白,直接 mov exa, count cdq idiv n 不就行了吗,eax取基址偏移,然后+4这是在干吗
应该是这里
fornetuse123 2016-03-25
  • 打赏
  • 举报
回复
引用 7 楼 fornetuse123 的回复:
sub eax, offset queue add eax, 4 cdq mov ecx, sizeof queue idiv n 这段真看不明白,直接 mov exa, count cdq idiv ecx 不就行了吗,eax取基址偏移,然后+4这是在干吗
红色那里错误了
fornetuse123 2016-03-25
  • 打赏
  • 举报
回复
sub eax, offset queue add eax, 4 cdq mov ecx, sizeof queue idiv ecx 这段真看不明白,直接 mov exa, count cdq idiv ecx 不就行了吗,eax取基址偏移,然后+4这是在干吗
闭才 2016-03-25
  • 打赏
  • 举报
回复
我是masm32v11r的 我在endm前加了nop 这个问题就解决了 不过又出现了新的问题 待我研究下 看值不值得讨论 感谢大神神之指令 另 请试下 e 5 看还正常吗
闭才 2016-03-25
  • 打赏
  • 举报
回复
引用 1 楼 fornetuse123 的回复:
搂主能解释下enqune中在进行什么操作么? 另外你main中好像忘记抄endif了
与其解释不如C代码直观 就是个入队的操作啊

	void enqueue()
			{
				if (count < n) 
				{
					count++;
					queue[rear] = number;
					rear=(rear+1)%n

				}
			}
这个真没有 或许是书里写错了 敢问endif加在哪里啊
闭才 2016-03-25
  • 打赏
  • 举报
回复
引用 2 楼 fornetuse123 的回复:
实现队列不就是系统创建一个缓冲区么,不是有基址和段限长了。你这又是加减又是乘除的在忙活什么呀?
可能是为了维护程序的可扩展性吧 加减乘除就是上面的C代码的实现 感觉还挺直观的啊
zara 2016-03-25
  • 打赏
  • 举报
回复
vs2015, 汇编器什么版本,它有问题?刚用 masm32v7 的 ml.exe (6.14.8444) 试了下,是正常的。
或者,你在那个宏的 endm 前加个 nop 指令看看?
fornetuse123 2016-03-25
  • 打赏
  • 举报
回复
实现队列不就是系统创建一个缓冲区么,不是有基址和段限长了。你这又是加减又是乘除的在忙活什么呀?
fornetuse123 2016-03-25
  • 打赏
  • 举报
回复
搂主能解释下enqune中在进行什么操作么? 另外你main中好像忘记抄endif了

21,459

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧