1

Hello All! I'm doing a MASM course and I got into this exercise. I have this simple assembly code:

.386
.model flat,c

.data
    quote   byte    "Machines do feel", 0
    message byte    SIZEOF quote DUP(0),0

.code

start proc
    
    mov esi,0
    mov ecx,SIZEOF quote

LP: 
    mov al,quote[esi]
    mov message[esi],al
    inc esi
    loop LP

    ret

start endp
    end

And I want to write a C++ program that can "printf" the variable "message".

How can I do this?

I tryed to add:

mov eax, DWORD ptr [message]

To the ".asm" file to store the address of the message variable on the register returned by the function and then I wrote this program to try to printf the values:

#include <iostream>

extern "C" char *start();

int main(){

    char *message = start();

    for(int i = 0x0; i < sizeof(message)/sizeof(char); i++){
        printf("%s", message[i]);
    }

    return 0x0;
}

But when I try to run it I get the error:

Unhandled page fault on read access to 6863614D at address 0040162E (thread 0024), starting debugger...
0024:err:seh:start_debugger Couldn't start debugger L"winedbg --auto 32 68" (2)

Can you please explain me how can I print the values of the ".asm" file "message" variable? And can also show me different methods to do this?

Thank you so much, have a nice coding!

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Z3R0
  • 1,011
  • 10
  • 19
  • 2
    `sizeof(message)/sizeof(char)` is very unlikely to give you the result that you expect. It is equal to `sizeof(char*)` which will most likely be either 4 or 8 (depending whether you compiled as 32 or 64 bit application) – UnholySheep May 30 '22 at 19:16
  • @UnholySheep Yeah I know I was just trying some methods to print out the variable but I always get the error I wrote on the question even if I change the for loop :/ Do you know ho can I print it? Like if I do the loop for 10 times (for example) instead of using the sizeof I still get the same error – Z3R0 May 30 '22 at 19:18
  • 3
    `printf("%s", message[i]);` is also fundamentally wrong, you are passing a `char` when the specifier `%s` expects a `char*`. Perhaps you meant to use `%c`? – UnholySheep May 30 '22 at 19:20
  • @UnholySheep True story, you're right! "%c" is the right formatter xD Silly me lol But I still get the same error :/ – Z3R0 May 30 '22 at 19:25
  • I'm also not sure your assembly function is correct. AFAIK you should be writing the return value into `eax` but I don't see you doing that anywhere. And presumably you want the return value to be the address of `message`. ( Your statement of "I tried to add" is too vague to tell whether you did that at the wrong place either) – UnholySheep May 30 '22 at 19:38
  • `"%s"` is corrects, it's the `[i]` that is wrong. `message` is a C style string, just print it. No loop required. – Goswin von Brederlow May 30 '22 at 20:16
  • What does `loop LP` do? How will the loop ever stop? You forgot to test `al` for `0`. – Goswin von Brederlow May 30 '22 at 20:21
  • 2
    @GoswinvonBrederlow : the LOOP instruction uses the value in ECX as a counter. They set ECX to the length of the string before the loop. The loop is terminated when ECX becomes zero. Looks like the code was trying to copy the quote to message. – Michael Petch May 30 '22 at 21:34
  • Ahh, then it makes sense. So `printf("%s", message);` should work. Or since this is c++: `std::cout << message;` – Goswin von Brederlow May 30 '22 at 21:35
  • @GoswinvonBrederlow With "%s" I get the same error: ne a.exe wine: Unhandled page fault on read access to 6863614D at address 6A2D0E24 (thread 0024), starting debugger... 0024:err:seh:start_debugger Couldn't start debugger L"winedbg --auto 32 68" (2) – Z3R0 May 30 '22 at 21:51
  • Code I used: #include extern "C" char *start(); int main(){ char *message = start(); printf("%s", message); return 0x0; } – Z3R0 May 30 '22 at 21:51
  • You don't return the address of `message` in EAX before returning – Michael Petch May 30 '22 at 22:04
  • 2
    I see you suggested you tried `mov eax, DWORD ptr [message]`. That moves the first 4 bytes starting at `message` to EAX not the address. You may have meant to use `mov eax, OFFSET message` to put the address in EAX. – Michael Petch May 30 '22 at 22:05
  • 1
    `6863614D` == Mach – Goswin von Brederlow May 30 '22 at 22:16
  • 3
    Since you are building win32 apps on Linux and running them in Wine I'd recommends using the GDB cross debugger as suggested in this answer https://stackoverflow.com/a/68268087/3857942 . Then you can find any tutorial on the GDB debugger. It's not hard to set breakpoints and step through code. To add debug symbols when assembling using JWASM add the option `-zI` option. Compile g++ code with `-g` for debug symbols. – Michael Petch May 31 '22 at 00:04
  • @MichaelPetch Thanks with OFFSET works. I though DWORD ptr [message] was used to move the address of the variable. Why it's used the OFFSET instruction instead? – Z3R0 May 31 '22 at 20:14
  • 1
    Just the way the MASM assembler syntax was designed. Certain aspects of MASM's syntax can be confusing for new people especially with how `[` `]` work. – Michael Petch May 31 '22 at 20:27
  • @MichaelPetch And if I'd like to print one character at time of the "message" string how can I retrieve the length of the "message" string? The only way is to iterate until I find the null terminator or there is another way to directly retrieve the length of the string? Is possibile to do something like (endAddress - startAddress) / char size? If yes how I retrieve the endAddress? – Z3R0 Jun 01 '22 at 22:18

0 Answers0