Hey,

I hope I'm in the right sub. I'm trying to write a simple put_pixel routine in assembly using nasm to compile. Somehow my code produces the wrong memory offset.

This is my put_pixel code:


global _put_pixel

section .text
_put_pixel:
; y*WIDTH
mov eax,
mov ebx, 8
mul ebx

;        + x
mov ebx,
add eax, ebx

;              + buffer
mov edx, dword
add eax, edx

ret


To cross check the resulting offset in EAX I'm using this C++ snippet:


#include <stdio.h>
#include <memory.h>

extern "C" int put_pixel(int* buffer, int x, int y, int color);

#define WIDTH 8
#define HEIGHT 8

int main()
{
int* buffer = new int ;
memset(buffer, 0, sizeof(int)*WIDTH*HEIGHT);
int color = 16777215, x=4, y=4;
int test = put_pixel(buffer, x, y, color);
        int test2 =  y*WIDTH+x+buffer;
printf("%10d\n", test);
printf("%10d\n", test2);
delete buffer;
return 0;
}


The resulting offset in test is always 108 bytes smaller than the one in test2. Can someone give a hint on what's wrong in my assembly code.

TIA,
paris
Posted on 2005-06-06 14:44:39 by Parasight
I see nothing wrong with your ASM code, except that it doesn't actually put the pixel ;) you're never reading the color parameter from the stack, not setting it's value in the buffer.

I'm not sure how NASM expects numbers to be, in decimal or hexa, you could try using hexa just to be on the safe side.

I'd stay away from modifying EBX too, the compiler expects it's value to be preserved by the function (this also counts for EBP, ESI and EDI).

Also you're returning the wrong value, in EAX you should put whatever you want the procedure to return (currently it just has the pointer to the pixel set).

If you want to return the previous pixel value (I'm guessing), you can use something like this instead:

; y*WIDTH
mov eax,
mov edx, 8
mul edx
; + x
mov edx,
add edx, eax
; + buffer
add edx,
; set the pixel
mov eax,
xchg eax,
; return the previous value
ret


Hope that helps! :)
Posted on 2005-06-06 15:11:46 by QvasiModo
QvasiModo,

thanks for the tips. You're right. I don't put the pixel in the code. I just return the memory offset ... at least i think so. I do it to check it it against the one calculated in C++.

The offset from the put_pixel routine is different from the one calculated by

y*WIDTH+x+buffer


and the pixel is put in the wrong position.

I do use EDX instead of EBX and hex numbers now. But still the memory offset calculated by the assembly routine is 108 less than the one calculated in C++.


global _put_pixel

section .text
_put_pixel:
; y*WIDTH
mov eax,
mov edx, 8
mul edx

;        + x
mov edx,
add edx, eax

;              + buffer
add edx,

; set the pixel
mov eax,
xchg eax,

ret
Posted on 2005-06-06 16:14:31 by Parasight
Try this...


WIDTH equ 8

ARG_BUF equ 0x04
ARG_X  equ 0x08
ARG_Y  equ 0x0C

global _put_pixel

section .text

_put_pixel:
    mov    eax, WIDTH
    xor    edx, edx
    mul    dword     ; y*WIDTH
    add    eax,       ; +x
    add    eax,     ; +buffer

    ret


EDIT: - you don't have a function prototype for put_pixel in your C code, and you should either fix the ESP offset or not pass the 'color' argument.
Posted on 2005-06-06 16:32:15 by f0dder

thanks for the tips. You're right. I don't put the pixel in the code. I just return the memory offset ... at least i think so. I do it to check it it against the one calculated in C++.


And I should have realized that by reading the test code more carefully... sorry for the noise then :(


The offset from the put_pixel routine is different from the one calculated by

y*WIDTH+x+buffer


and the pixel is put in the wrong position.

I do use EDX instead of EBX and hex numbers now. But still the memory offset calculated by the assembly routine is 108 less than the one calculated in C++.


global _put_pixel

section .text
_put_pixel:
; y*WIDTH
mov eax,
mov edx, 8
mul edx

; + x
mov edx,
add edx, eax

; + buffer
add edx,

; set the pixel
mov eax,
xchg eax,

ret



It should be 10h, not 0Ah. :)

Try this...


WIDTH equ 8

ARG_BUF equ 0x04
ARG_X equ 0x08
ARG_Y equ 0x0C

global _put_pixel

section .text

_put_pixel:
mov eax, WIDTH
xor edx, edx
mul dword ; y*WIDTH
add eax, ; +x
add eax, ; +buffer

ret



You're right, as usual. :)


EDIT: - you don't have a function prototype for put_pixel in your C code, and you should either fix the ESP offset or not pass the 'color' argument.


Uh? Now you've lost me...
Posted on 2005-06-06 16:37:44 by QvasiModo

Uh? Now you've lost me...

Oops - he *did* have the function prototype, I just missed it. I blame all the reading I've had to do because of exams - never mind that EDIT text ;)
Posted on 2005-06-06 16:47:06 by f0dder


Uh? Now you've lost me...

Oops - he *did* have the function prototype, I just missed it. I blame all the reading I've had to do because of exams - never mind that EDIT text ;)

I can relate! :D
Posted on 2005-06-06 16:49:39 by QvasiModo


global _put_pixel

section .text
_put_pixel:
; y*WIDTH
mov eax,
mov ebx, 8
mul ebx

;? ? ? ? ?+ x
mov ebx,
add eax, ebx

;? ? ? ? ? ? ? + buffer
mov edx, dword
add eax, edx

ret



Here is the problem:


int* buffer = new int ;

? ? ? ? int test2 =? y*WIDTH+x+buffer;


Because buffer is a pointer to ints, the C compiler automatically scales the nonpointer values.

The last few instructions should be

	;? ? ? ? ?+ x
mov ebx,
add eax, ebx

; *** Add this line...
shl? ? ?eax, 2? ? ? ?; To get correct offset, multiply by 4, the size of an int (DWORD)
; ***

;? ? ? ? ? ? ? + buffer
mov edx, dword
add eax, edx


Posted on 2005-06-06 17:15:05 by tenkey
This is definitely not my day... :(
Posted on 2005-06-06 17:17:53 by QvasiModo
Ah! Now I see the light :D

Thank you all very much!
Posted on 2005-06-07 04:17:45 by Parasight