程序中断,我不明白为什么

时间:2014-11-24 17:33:35

标签: assembly x86 masm irvine32

这是我编写的最新一段代码。我想弄清楚几件事。

问题:我想我几乎拥有它,但是它说每个PIN都是有效的,但它不是。这意味着ValidatePIN过程是错误的,但我似乎无法弄明白。有什么建议吗?

非常感谢你的帮助!!!!!

; 32-bit assembly language template

; INCLUDE Irvine32.inc

INCLUDELIB C:\Irvine\Kernel32.lib
INCLUDELIB C:\Irvine\Irvine32.lib
INCLUDE C:\Irvine\Irvine32.inc

pbyte typedef ptr byte                          ; pointer to bytes

.data
VALID_PIN = 0
PIN_SIZE = 5
minVals byte 5,2,4,1,3                  ; globally visible
maxVals byte 9,5,8,4,6                  ; globally visible
samplePin_1 byte 6,3,4,4,3              ; valid PIN
samplePin_2 byte 5,2,3,2,4              ; digit 3 is invalid
samplePin_3 byte 5,2,4,5,3              ; digit 4 is invalid
samplePin_4 byte 1,3,4,4,3              ; digit 1 is invalid

ptr1 pbyte samplePin_1                          ; points to array samplePin_1
ptr2 pbyte samplePin_2                          ; points to array samplePin_2
ptr3 pbyte samplePin_3                          ; points to array samplePin_3
ptr4 pbyte samplePin_4                          ; points to array samplePin_4
ptr5 pbyte minVals                              ; points to array minVals
ptr6 pbyte maxVals                              ; points to array maxVals

ValidPINMsg byte "The PIN is valid     ", 0    ;
InvalidPINMsg byte "The PIN is invalid.  The invalid digit is     ", 0 ;

.code
main proc

mov eax,VALID_PIN                  ; 

mov edi,ptr5
mov ebp,ptr6

mov esi,ptr1
call ValidatePIN                   ; determine whether or not the PIN is valid
.IF eax == ecx
 mov edx,OFFSET ValidPINMsg
 call WriteString
 call WaitMsg
 call Crlf
.ELSE
 mov edx,OFFSET InvalidPINMsg
 call WriteString
 call WriteDec
 call WaitMsg
 call Crlf
.ENDIF

mov esi,ptr2
call ValidatePIN                   ; determine whether or not the PIN is valid                       
.IF eax == ecx
 mov edx,OFFSET ValidPINMsg
 call WriteString
 call WaitMsg
 call Crlf
.ELSE
 mov edx,OFFSET InvalidPINMsg
 call WriteString
 call WriteDec
 call WaitMsg
 call Crlf
.ENDIF

mov esi,ptr3
call ValidatePIN                   ; determine whether or not the PIN is valid                       
.IF eax == ecx
 mov edx,OFFSET ValidPINMsg
 call WaitMsg
 call Crlf
.ELSE
 mov edx,OFFSET InvalidPINMsg
 call WriteString
 call WriteDec
 call WaitMsg
 call Crlf
.ENDIF

mov esi,ptr4
call ValidatePIN                   ; determine whether or not the pin is valid                       
.IF eax == ecx
 mov edx,OFFSET ValidPINMsg
 call WriteString
 call WaitMsg
 call Crlf
.ELSE
 mov edx,OFFSET InvalidPINMsg
 call WriteString
 call WriteDec
 call WaitMsg
 call Crlf
.ENDIF

main endp

ValidatePIN PROC
 mov ecx,PIN_SIZE

 .REPEAT

.IF (esi < edi) || (esi > ebp)
    call L1
.ELSE
 add esi,1
 add edi,1
 add ebp,1
.ENDIF

dec ecx    

.UNTIL ecx == 0

L1: 
 mov eax,ecx
 ret

ret
ValidatePIN ENDP
END main

1 个答案:

答案 0 :(得分:1)

问题#1:您在exit末尾忘记了mainret末尾忘记了ValidatePIN

问题#2:Irvine32.lib有一个CRLF-function。在您想要换行的位置插入call CrLf

问题#3:通常,函数会在EAX中返回结果。调用者可以评估EAX中的此值。在汇编中,您可以自由返回其他寄存器中的其他值。使用Irvine32.lib,您可以print the value of EAX decimal

还有其他有用的功能。看看whole help for Irvine32.inc (with frameset)

<强>附录:

还有其他问题:

call ValidatePIN                   ; determine whether or not the PIN is valid
.IF eax == ecx
 mov edx,OFFSET ValidPINMsg
...
.ELSE
...

EAX什么时候应该变得不等于ECXValidatePIN的最后一条指令是mov eax,ecx,因此此时EAXECX始终相等。你的意思是.IF eax == 0

mov esi,ptr2
call ValidatePIN                   ; determine whether or not the PIN is valid
...
最后一个程序(EDI)修改了

EBPcall ...。你必须再次初始化它们。

.IF (esi < edi) || (esi > ebp)
...

ESIEDIEBP在这里是指针(即内存地址)不是值。要获取值,您必须用方括号装饰指针。但是你无法在x86-assembly中直接比较内存和内存。下一个问题是保证只比较一个字节而不是双字。 TL; DR:

mov al, byte ptr [esi]
.IF (al < [edi]) || (al > [ebp])
...

ALEAX的最低字节。 MASM现在认识到,您只需要进程字节。

call L1

call将返回。我想你想在这一点上中止循环。因此:

jmp L1

您不会喜欢无效数字的编号。 ECX(确定返回EAX)在循环中倒计时:5-4-3-2-1-0。要获得“计数”,您必须计算(6 - ECX),但保持ECX = 0不变。您可以将该字词转换为(-ECX + 6)。所以,改变

.IF (al < [edi]) || (al > [ebp])
    jmp L1
.ELSE
...

.IF (al < [edi]) || (al > [ebp])
    neg ecx
    add ecx, 6
    jmp L1
.ELSE
...