2016-11-19 30 views
1

所以我想让一个用户输入一个字符串,并且我需要保留字母在用户字符串中的出现次数。防爆。 “你好”H = 1,e = 1,l = 2,依此类推。将BYTE参数传递给使用INVOKE MASM的过程

但是,我无法将大小为BYTE的指针和字符串的最大长度为132个字符传递给我的过程GetNumLetters。

当我得到的字符串的长度为例如“你好”stringLength = 5但是当我将stringLength传递给我的过程存储该值(arrayLength)的参数不等于5,但是像一些疯狂的数字8398473 。我只是不明白为什么arrayLength不等于5当我将stringLength传递给函数GetNumLetters。 (我没有测试过其余的函数,因为我无法获得字符串的大小)。

我的想法是,stringLength传递8位和其他24位随机填充。但是,我不知道在这种情况下,我会如何填充类型转换字符串长度为32位,高位24位= 0。

INCLUDE Irvine32.inc 

INCLUDE Macros.inc 

GetNumLetters PROTO, arrayInput: PTR BYTE, arrayCount: PTR BYTE, arrayLength: BYTE 
PrintNumLetters PROTO, arrayCount: PTR BYTE, arrayLength: BYTE 

.data 

charInput BYTE 132 DUP (?) ;an array that stores the users input of 132 values 

charCount BYTE 123 DUP (0)  ;an array to store the instances of letters ONLY CARE ABOUT ASCII CHAR A-Z,a-z,0-9 

stringLength BYTE 0    ;length of the string 

msg BYTE "Enter String: ",0 


.code 
main proc 

    xor edx, edx 
    xor eax, eax 
    xor ecx, ecx 
    mov edx, OFFSET msg 
    Call WriteString 
    mov edx, OFFSET charInput ;point to buffer you want input stored 
    mov ecx, SIZEOF charInput ;specify length of string 
    call ReadString    ;get string from user 
    mov stringLength, BYTE PTR eax ;make 32bit to 8bit 


    INVOKE GetNumLetters, OFFSET charInput, OFFSET charCount, stringLength 

    exit 
main ENDP 

;========================================================================== 

GetNumLetters PROC, arrayInput: PTR BYTE, arrayCount: PTR BYTE, arrayLength: BYTE 
    ;might need to put arrayInput and arrayCount into esi edi 
    push ecx 
    push eax 
    push ebp 
    mov ebp, esp 
    xor ecx, ecx 
    xor eax, eax 
    movzx ecx, arrayLength 

    movzx eax, arrayLength 
    call WriteDec 

    ;check for letters 0-9 
    LoopG1: 
      mov eax, DWORD PTR [arrayInput + ecx] 
      dec ecx       ;decrease loop counter 
      cmp eax, 48      ;check if eax < 0 
      jb LoopG1      ; if eax < 0 try another letter 
      cmp eax, 57      ;check if eax > 9 
      ja LoopG1      ; if eax > 9 try another letter 
      inc DWORD PTR [arrayCount + eax]   ;increment the letter's count 
      jmp LoopG1 

    xor ecx, ecx 
    mov ecx, DWORD PTR arrayLength 
    ;check for letters A-Z 
    LoopG2: 
      mov eax, DWORD PTR [arrayInput + ecx] 
      dec ecx       ;decrease loop counter 
      cmp eax, 65      ;check if eax is < A 
      jb LoopG2      ; if eax < A try another letter 
      cmp eax, 90      ;else check if eax > Z 
      ja LoopG2      ; if eax > Z try another letter 
      inc DWORD PTR [arrayCount + eax]   ;increment the letter's count 
      jmp LoopG2 

    xor ecx, ecx 
    mov ecx, DWORD PTR arrayLength 
    ;check for letters a-z 
    LoopG3: 
      mov eax, DWORD PTR [arrayInput + ecx] 
      dec ecx       ;decrease loop counter 
      cmp eax, 97      ;check if eax is < a 
      jb LoopG3      ; if eax < a try another letter 
      cmp eax, 122     ;else check if eax > z 
      ja LoopG3      ; if eax > z try another letter 
      inc DWORD PTR [arrayCount + eax]   ;incrememnt the letter's count 
      jmp LoopG3 
    pop ebp 
    pop eax 
    pop ecx 
    ret 12  ;return 12 bytes to esp for the 3 parameters (take up 4 bytes each) 
       ; even though they are BYTE 
GetNumLetters ENDP 
+0

为什么不使用反汇编程序来查看MASM为'INVOKE GetNumLetters,OFFSET charInput,OFFSET charCount,stringLength'行做了什么?大多数调试器应该有内置的反汇编程序,听起来您已经在使用调试器了。但无论如何,您不需要使用这些伪指令,只需编写自己的PUSH和CALL指令即可。 (请注意,没有'PUSH r/m8',所以很可能它会推送垃圾,并且你的函数显然不会忽略它。还要注意,你可以将'stringLength'定义为EQU常量,而不是从MEM)。 –

回答

0

你为什么不使用反汇编器,看看有什么MASM做了INVOKE GetNumLetters, OFFSET charInput, OFFSET charCount, stringLength线?大多数调试器应该有内置的反汇编程序,听起来您已经在使用调试器了。

但无论如何,您不需要使用这些伪指令,只需编写自己的PUSH和CALL指令即可。

Note that there is no PUSH r/m8,所以它最有可能推动垃圾一起你的字节,你的功能显然不会忽略它。

另请注意,您可以将stringLength定义为EQU常量,而不是从mem中加载它。


你可能还打破MASM企图通过前push ebp/mov ebp, esp做其他推来帮助你。我不知道MASM,但我认为GetNumLetters PROC, arrayInput: PTR BYTE, arrayCount: PTR BYTE, arrayLength: BYTE会为您生成一些序言,或者将这些名称定义为来自EBP的偏移量,它假定您在函数输入中首先设置堆栈帧。

再一次,用数字偏移看实际的反汇编,看看究竟发生了什么。

请注意,通常的调用约定是EAX,ECX和EDX被调用,所以您应该编写函数来假定他们调用的任何函数都会打开这些regs,并且在您自己的函数中不会浪费保存/恢复它们的说明。即完全删除push ecxpush eax,而不是在push ebp之后移动它们。

相关问题