CallumDev
CallumDev

Reputation: 239

Retrieving a word from a string literal?

In NASM I have strconst_0 dw 5, 0, __utf16__('hello') (with single backticks) as a string

I'm trying to access the 'h' like this (where [ebp+8] is 0 and [ebp+4] is the address of the string)

mov eax, [ebp+8] ; get the index
mov ebx, [ebp+4] ; get the address
movzx eax, word [ebx + 2 * eax + 4]
push eax
call print_char ; call the print function

However, when I run this code, only an empty character is printed

EDIT: Full listing

main:
pop edx
push ebp
mov ebp, esp
sub esp, 4
mov [ebp-4], edx
mov eax, strconst_0
push eax
push dword 0
call getChar
add esp, 8
push eax
call printChar
add esp, 4
mov edx, [ebp-4]
add esp, 4
pop ebp
push edx
ret

getChar:
pop edx
push ebp
mov ebp, esp
sub esp, 4
mov [ebp-4], edx
mov eax, [ebp+8]
mov ebx, [ebp+4]
movzx eax, word [ebx + 2 * eax + 4]
push eax
pop eax
mov edx, [ebp-4]
add esp, 4
pop ebp
push edx
ret

Upvotes: 0

Views: 377

Answers (2)

CallumDev
CallumDev

Reputation: 239

I got the arguments the wrong way around. If I swap ebx and eax in the inital mov instructions, it works fine.

Upvotes: 1

Dmytro
Dmytro

Reputation: 5213

  1. you pop the return address of main into edx at start of your program, this makes no sense.
  2. you have no comments at all, so I cannot possible understand what you are trying to do, as you have no prototype for your getChar.

basically, here's analysis, I do not have the tools on me so I made a few assumptions

main:
    ; why is return address of main popped into edx?
    pop        edx

    ; standard stack setup                   
    push       ebp
    mov        ebp,      esp

    ; make space for 4 bytes
    sub        esp,      4

    ; store edx in where return address used to be... why?
    mov        [ebp-4],  edx

    ; move address of strconst_0 to eax
    mov        eax,      strconst_0

    ; push eax on stack
    push       eax

    ; push 4 bytes 0x00000000 on stack
    push dword 0

    ; call getchar(0, strconst_0)
    call       getChar

    ; restore stack
    add        esp,      8

    ; push eax which was mutated in getChar on stack
    push       eax

    ; printChar(eax)
    call       printChar

    ; restore stack
    add        esp,      4

    ; move whatever we overwritten old return address to, to edx
    mov        edx,      [ebp-4]

    ; restore stack
    add        esp,      4
    pop        ebp

    ; restore return address
    push       edx

    ; return
    ret

; what do I accept(on stack)
; what do I return(in eax)
getChar:
    ; again, seems silly
    pop edx

    ; obvious
    push ebp
    mov        ebp,      esp

    ; make space for 4 bytes on stack
    sub        esp,      4

    ; overwrite return address with edx
    mov        [ebp-4],  edx

    ; I am guessing you are trying to get the two arguments into eax, ebx

    ; eax = 0
    mov        eax,      [ebp+8]
    ; ebx = strconst_0
    mov        ebx,      [ebp+4]
    ; magic is here
    movzx      eax,      word [ebx + 2 * eax + 4]
    ; push magic number
    push       eax
    ; pop ... something into eax
    pop        eax
    ; restore edx from whatever you put there...
    mov        edx,      [ebp-4]
    ; restore stack?
    add        esp,      4

    ; obvious
    pop        ebp
    push       edx
    ret

Honestly, I have no idea what you are doing, it would help if you say something along the lines of "I am trying to make a function which accepts a ? and the address of the string buffer, which ?"

In particular, 1. I have no idea what getChar inputs are, is it position of character? is it something else? 2. I have no idea what getChar outputs are, does it store something in eax? does it launch the missiles? 3. I have no idea why you use your function's return address for temporary storage, it is silly.

main:
    push           ebp
    mov            ebp,                esp

    ; getChar(0, str)
    push           str
    mov dword      eax,                0
    push           eax
    call           getChar
    add            esp,                8

    ; printChar(str)
    push           str
    call           printChar
    add            esp,                4

    mov            esp,                ebp
    pop            ebp
    ret

; char getChar(long ix, char *str)
; returns: char at index indicated by ix in eax register
getChar:
    push           ebp
    mov            ebp,                esp
    push           ebx   ; save ebx to avoid unwanted side-effects

    mov            eax,                [ebp + 8]    ; ix
    mov            ebx,                [ebp + 12]   ; str
    add            eax,                ebx    ; eax = &(str[ix])
    mov            eax,                (eax)  ; eax = *eax = str[ix]

    pop            ebx  ; restore ebx
    mov            esp,                ebp
    pop            ebp
    rts

str db 'this is a string.', 0

This is definitely not going to work, and given purely for demonstrational purposes since I have not written x86 in a while, the idea should be clear though. Hope it helps.

Upvotes: 0

Related Questions