试图弄清楚 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 语法的主要内容,如果未能解决你的问题,请参考以下文章