Harry
Harry

Reputation: 179

Trying to figure out MASM syntax

I've done some assembly programming on Linux and am now trying to do it on Windows using MASM. I am running into a couple issues though.

(Here I am trying to implement the strlen() function. I know the function logic/instructions aren't optimal, but I'm just trying to rig something dirty up so I can get going on implementing other C library functions.)

.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

When I try to compile, it doesn't appear to like my jmp labels, throwing unmatched macro nesting, etc. Whats the proper way to do this? p.s. I am trying to avoid using MASM macros where possible, preferring to code the instructions myself.

Can someone please make this program compile? Once I see how it is done correctly I will be on my merry way, I will be able to. Yes I looked for resources and still am as this question is up.

Upvotes: 4

Views: 1515

Answers (2)

f6a4
f6a4

Reputation: 1782

This is a solution with macros. The length of the string is finally stored in EAX.

First macro checks a whole DWORD from the memory and is faster than a bytewise read and check. Good for larger strings.

;//-----------------------------------------------------------------------
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

A short solution with bytewise check:

;//-----------------------------------------------------------------------
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

In main proc:

.data

        anyString byte "Hello World", 0

    .code
        main PROC

        strlenShort OFFSET anyString        ;// => result in EAX

        strlenFast OFFSET anyString     ;// => result in EAX

Upvotes: 0

rkhb
rkhb

Reputation: 14399

Can someone please make this program compile?

Voilà (explanation in the comments):

.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

I suspect you want to output the result of my_strlen. This is not possible with StdOut because StdOut needs a pointer to a string. You have to create a function to convert EAX to a string.

Upvotes: 3

Related Questions