试图弄清楚 MASM 语法

Posted

技术标签:

【中文标题】试图弄清楚 MASM 语法【英文标题】:Trying to figure out MASM syntax 【发布时间】:2014-09-11 20:20:46 【问题描述】:

我已经在 Linux 上进行了一些汇编编程,现在正尝试在 Windows 上使用 MASM 进行。不过,我遇到了几个问题。

(这里我正在尝试实现 strlen() 函数。我知道函数逻辑/指令不是最佳的,但我只是想弄脏一些东西,以便继续实现其他 C 库函数.)

.386
.model flat, stdcall
option casemap:none

include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib

include \masm32\include\masm32.inc
includelib \masm32\lib\masm32.lib

.data
       testString db "test string", 0   ; 0 -> terminator

.code
my_strlen proc
        mov ebp, esp                    ; function prologue
        push esp
        push ebx
        push ecx

        xor ecx, ecx                    ; set count to 0
        mov bl, byte ptr [ebp + 8]      ; set low of b to 1st character

    repeat:
        cmp bl, 0                           ; if null terminator, return
        jz done
        inc ecx                             ; increase count
        mov bl, byte ptr [ebp + 8 + ecx]    ; increase *ebx
        jmp repeat                          ; repeat

    done:

        mov eax, ecx                    ; return count

        pop ecx                         ; function epilogue
        pop ebx
        pop esp
        ret

my_strlen endp


main:
       push offset testString                       ; result = my_strlen(testString)
       call my_strlen

       push eax                                     ; StdOut(result)
       call StdOut

       push 0                                       ; ExitProcess(0)
       call ExitProcess                              
end main

当我尝试编译时,它似乎不喜欢我的 jmp 标签,抛出不匹配的宏嵌套等。这样做的正确方法是什么? p.s.我尽量避免使用 MASM 宏,而是自己编写指令。

有人可以编译这个程序吗?一旦我看到它是如何正确完成的,我就会走上快乐的道路,我将能够做到。是的,我在寻找资源,但仍然存在这个问题。

【问题讨论】:

我认为“重复”可能是一个糟糕的选择。我认为它是一个 MASM 关键字,用于管理宏的重复。 @Harry 在我开始我的实验之前,请试试这个:将单词 repeat: 更改为 George: 之类的东西。 Repeat这个词对MASM的Macro部分有特定的含义 @IraBaxter 请关闭你的读心调制解调器! 您应该包含您收到的确切错误消息。如果你得到很多,你只能包括前几个。 【参考方案1】:

有人可以编译这个程序吗?

瞧(在 cmets 中的解释):

.386
.model flat, stdcall
option casemap:none

include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib

include \masm32\include\masm32.inc
includelib \masm32\lib\masm32.lib

.data
    testString db "test string", 0

.code
my_strlen proc

;   mov ebp, esp                        ; function prologue
;   push esp

    push ebp                            ; this is a correct prologue
    mov ebp, esp

    push ebx
    push ecx
    push esi

    mov esi, [ebp+8]                    ; in [EBP+8] is a pointer

    xor ecx, ecx
    mov bl, byte ptr [esi]

    repea:                              ; "repeat" is a keyword
        cmp bl, 0
        jz done
        inc ecx
        mov bl, byte ptr [esi + ecx]    ; increase *esi
        jmp repea                       ; repeat

    done:
        mov eax, ecx

        pop esi
        pop ecx
        pop ebx

        leave                           ; this is a correct epilogue
        ret

my_strlen endp


main proc                               ; this is better
       push offset testString
       call my_strlen

;      push eax                         ; StdOut(result)
       push offset testString           ; The MASM32-function StdOut needs only an ASCIZ-string
       call StdOut

       push 0                
       call ExitProcess
main endp

end main

我怀疑你想输出 my_strlen 的结果。这对于StdOut 是不可能的,因为StdOut 需要一个指向字符串 的指针。您必须创建一个函数来将EAX 转换为字符串。

【讨论】:

【参考方案2】:

这是一个带有宏的解决方案。字符串的长度最终存储在 EAX 中。

第一个宏从内存中检查整个 DWORD,比按字节读取和检查要快。 适合较大的字符串。

;//-----------------------------------------------------------------------
strlenFast MACRO stringPtr:REQ
;//-----------------------------------------------------------------------
local STRLEN_LOOP

    mov eax, stringPtr
    mov esi, 0

    STRLEN_LOOP:
        mov ebx, [eax+esi]
        mov ecx, ebx
        inc esi     
        and ebx, 0FFh
        jz EOS
        mov ebx, ecx
        inc esi
        and ebx, 0FF00h
        jz EOS
        mov ebx, ecx
        inc esi
        and ebx, 0FF0000h
        jz EOS
        mov ebx, ecx
        inc esi
        and ebx, 0FF000000h
    jnz short STRLEN_LOOP

    EOS:
    dec esi
    mov eax, esi

ENDM

字节检查的简短解决方案:

;//-----------------------------------------------------------------------
strlenShort MACRO stringPtr:REQ
;//-----------------------------------------------------------------------
local STRLEN_LOOP

    mov eax, stringPtr
    mov esi, -1

    STRLEN_LOOP:
        inc esi
        mov ebx, [eax+esi]
        and ebx, 0FFh
    jnz STRLEN_LOOP

    mov eax, esi

ENDM

在主进程中:

.data

        anyString byte "Hello World", 0

    .code
        main PROC

        strlenShort OFFSET anyString        ;// => result in EAX

        strlenFast OFFSET anyString     ;// => result in EAX

【讨论】:

以上是关于试图弄清楚 MASM 语法的主要内容,如果未能解决你的问题,请参考以下文章

想用Python做项目?先弄清楚这些基础的语法吧

YACC和LEX,在行尾获取语法错误,无法弄清楚原因

Java中的XML语法验证[关闭]

将 AngularJS 变量绑定到 CSS 语法中

masm 16位汇编语法

masm 16位汇编语法