Author Topic: Getting address of a local variable  (Read 9904 times)

Offline NinjiHaku

  • Jr. Member
  • *
  • Posts: 4
Getting address of a local variable
« on: August 11, 2014, 01:20:34 PM »
Hello!

I have a function that loads a bitmap file (for an OpenGL application). But I'm having a hard time trying to understand a few things, and I'd like to see if someone could place me in the right track.

Basically, I'm trying to translate a C program I coded into ASM using NASM. And the loader function starts like this:

Code: [Select]
loadBMP:
enter 32,0

;Function arguments
%define ebp_filepath ebp+8

;Local variables (8*DWORD = 32 bytes)
%define headerptr ebp-4 ;unsigned char array pointer (unsigned char*)
%define dataPos ebp-8 ;Offset of the RGB data in the file (unsigned int)
%define width_ ebp-12 ;Width of the image in pixels (unsigned int)
%define height_ ebp-16 ;Height of the image in pixels (unsigned int)
%define imageSize ebp-20 ;Size of the image in pixels (unsigned int)
%define fileptr ebp-24 ;Pointer to a FILE structure (FILE*)
%define dBuffPtr ebp-28 ;Data buffer (with the RGB information) (unsigned char*)
%define texID ebp-32 ;unsigned integer (GLuint) with the ID of our texture (GLuint = unsigned int)

My major doubt is when I reach the glGenTextures function. In C, it goes like this

Code: [Select]
glGenTextures(1, &textureID);
But then, I'm not sure how to obtain the address of my texID variable in the ASM code. I tried

Code: [Select]
mov eax, dword ptr texID
But it doesn't compile (it says it expects a colon or semicolon). So I don't know how to translate it. Here's the rest of the function, in case you want to check it:

Code: [Select]
loadBMP:
;Configrue the stack frame and reserve
;32 bytes for local variables
enter 32,0

;Function arguments
%define ebp_filepath ebp+8

;Local variables (8*DWORD = 32 bytes)
%define headerptr ebp-4 ;unsigned char array pointer
%define dataPos ebp-8 ;Offset of the RGB data in the file
%define width_ ebp-12 ;Width of the image in pixels
%define height_ ebp-16 ;Height of the image in pixels
%define imageSize ebp-20 ;Size of the image in pixels
%define fileptr ebp-24 ;Pointer to a FILE structure
%define dBuffPtr ebp-28 ;Data buffer (with the RGB information)
%define texID ebp-32 ;unsigned integer (GLuint) with the ID of our texture

;Allocate 54 bytes of memory. Get the pointer.
mov eax, 54
push eax
call _malloc
mov [headerptr], eax

;Open the file. Get the pointer to the FILE structure.
mov eax, file_open_mode
push eax
mov eax, file_open_path
push eax
call _fopen
mov [fileptr], eax

;TODO: Check for errors

;Load the header of the BMP file
mov eax, [fileptr]
push eax
mov eax, 54
push eax
mov eax, 1
push eax
mov eax, [headerptr]
push eax
call _fread

;Save the current ESI state in the stack
push esi

;Point ESI to our header structure, and read it
mov esi, [headerptr]

;Get the offset of the RGB information
mov eax, dword [esi+10]
mov [dataPos], eax

;Get the size of the image
mov eax, dword [esi+34]
mov [imageSize], eax

;Get the width and height
mov eax, dword [esi+18]
mov [width_], eax
mov eax, dword [esi+22]
mov [height_], eax

;TODO: Guess possible missing parameters

;Restore ESI
pop esi

;Allocate enough memory for the RGB buffer
mov eax, [imageSize]
push eax
call _malloc
mov [dBuffPtr], eax

;Get the RGB information.
mov eax, [fileptr]
push eax
mov eax, [imageSize]
push eax
mov eax, 1
push eax
mov eax, [dBuffPtr]
push eax
call _fread

;Close the file
mov eax, [fileptr]
push eax
call _fclose

;Generate a new Texture
;mov eax, [texID]
lea eax, [texID]
push eax
mov eax, 1
push eax
call [glGenTextures]

;Bind our texture to our current actions
;(It's a way of saying "Do the following actions to the current texture")
;mov eax, [texID]
mov eax, [texID]
push eax
mov eax, GL_TEXTURE_2D
push eax
call [glBindTexture]

;Load the bitmap information into our texture
mov eax, [dBuffPtr]
push eax
mov eax, GL_UNSIGNED_BYTE
push eax
mov eax, GL_BGR_EXT
push eax
xor eax, eax ;A faster way to do "mov eax, 0"
push eax
mov eax, [height_]
push eax
mov eax, [width_]
push eax
mov eax, GL_RGB
push eax
xor eax, eax
push eax
mov eax, GL_TEXTURE_2D
push eax
call [glTexImage2D]

;Set the parameters for our texture (mipmaps)
mov eax, GL_NEAREST
push eax
mov eax, GL_TEXTURE_MAG_FILTER
push eax
mov eax, GL_TEXTURE_2D
push eax
call [glTexParameteri]

mov eax, GL_NEAREST
push eax
mov eax, GL_TEXTURE_MIN_FILTER
push eax
mov eax, GL_TEXTURE_2D
push eax
call [glTexParameteri]

;stdcall convention: Return parameter goes in EAX
mov eax, [texID]
;Undo the stack frame configuration
leave
;stdcall convention: Clear the stack (4 bytes per argument)
ret 4
« Last Edit: August 11, 2014, 01:55:39 PM by NinjiHaku »

Offline gammac

  • Jr. Member
  • *
  • Posts: 71
  • Country: 00
Re: Getting address of a local variable
« Reply #1 on: August 11, 2014, 01:36:22 PM »
try

Code: [Select]
lea eax, [texID]
Please comment your code! It helps to help you.

Offline NinjiHaku

  • Jr. Member
  • *
  • Posts: 4
Re: Getting address of a local variable
« Reply #2 on: August 11, 2014, 01:50:11 PM »
I will! Thanks!

Also I updated my post with the ASM code of the program, instead of the C code (I wanted to post the ASM code), in case someone wants to check it and tell me something else about it.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Getting address of a local variable
« Reply #3 on: August 11, 2014, 01:58:33 PM »
Yeah, that's what I would guess. "Ptr" is Masm/Tasm (Intel) syntax. It doesn't really do anything, so we just leave it out for Nasm. It is a memory reference, so:
Code: [Select]
mov eax, [texID]
We could say "dword", but the size of the register determines the size of the operation anyway, so we don't need it.

However, the C code indicates that we want "&textureID" - the address of the variable, not the contents.
Code: [Select]
lea eax, [texID]
should give you that, as Gammac says.

If this were a static variable...
Code: [Select]
texID dw 42
...
mov eax, texID
would work, but since it's a local variable - %defined as ebp - 32...
Code: [Select]
mov eax, ebp - 32
isn't going to be valid syntax in any assembler.

Best,
Frank