I am having trouble with the following script:

.386
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib ;adding all my libs

.data
nsv db "APPDATA", 0 ;i want to use this in getenv();
fnsv db 260 dUP(0) ; char fnsv[260];
ffn db 260 dUP(0) ; char ffn[260];
mbt db "Test", 0 

tl db "getenv", 0 ;to call this later

.code
start:


push offset nsv ;pushing APPDATA 
push 260 ;pushing the max size? 260
call tl ;calling getenv

;getenv("APPDATA") should be stored in eax now

mov ffn, eax      ;move the path into char ffn[260];



invoke MessageBox, NULL, addr fnsv, addr mbt, MB_OK + MB_ICONINFORMATION ;show a msgbox displaying path

invoke ExitProcess, NULL ;exit

end start

I get these errors:
C:\Users\Canada FTW\Desktop\nsv.asm(26) : error A2024: invalid operand size for
instruction
C:\Users\Canada FTW\Desktop\nsv.asm(28) : error A2070: invalid instruction opera
nds


I am new to mASM, so I am not really sure what the problem would be. I left a few notes so you guys could understand what I was doing. I am not really sure how to fix this, can you even call getenv in assembly? or would it be more difficult than this?

char *ffn = getenv("APPDATA"); but in massembly. This script was made from looking at the following script in ollydbg.

#include <windows.h>

int main()
{
char *path = getenv("APPDATA");
}

Dani AI

Generated

Two separate issues caused the assembler errors you saw.

First: calling a data label. The line that defines tl db "getenv",0 creates a string in the data section. Using call on that label tries to execute the string as code — not how you call an imported routine. getenv is provided by the C runtime, not by kernel32, so you either link the C runtime import (and call the exported name properly) or use the Windows API function that fills a caller-supplied buffer (recommended on Windows). As suggested, prefer the kernel32 environment call because it writes into your buffer directly and avoids CRT pointer lifetime issues.

Second: operand-size mismatch. mov ffn, eax fails because ffn was declared as a byte array; the assembler needs the destination size to match the register size. If your intention was to store the pointer value returned in EAX, declare a dword and store into it. If you intended to copy the string contents pointed to by EAX into your 260‑byte buffer, you must perform an actual string copy, not a single mov.

Quick fixes (conceptual examples):

; to store the pointer value (no string copy)
ffn_ptr dd 0
; after call returns pointer in EAX
mov [ffn_ptr], eax
; to copy the returned C string into your buffer (use the imported copy routine)
invoke lstrcpyA, addr myBuf, eax    ; copies the null-terminated string

Practical tips:

  • Use SIZEOF or LENGTHOF for buffer sizes rather than hard-coding 260.
  • When using the Windows API check the return: GetEnvironmentVariable returns required length (or 0 on error); if return >= buffer size you need a larger buffer.
  • Be mindful of ANSI vs Unicode: use the A/W variants consistently and declare buffers accordingly.
  • If you do call CRT getenv, link the correct import library and remember it returns a pointer to an internal buffer (copy it if you need a stable copy).

Thanks to for pointing you toward the Windows API approach — it’s usually the simplest and safest on Win32.

Recommended Answers

All 2 Replies

You don't need line 18 or line 25 as getenv only takes one argument, that being a string pointer.

I generally like using kernel32 library functions and in this case may work for you

GetEnvironmentVariable

The GetEnvironmentVariable function retrieves the value of the specified variable from the environment block of the calling process. The value is in the form of a null-terminated string of characters.

DWORD GetEnvironmentVariable(
LPCTSTR lpName, // address of environment variable name
LPTSTR lpBuffer, // address of buffer for variable value
DWORD nSize // size of buffer, in characters
);

Line 26 would be replaced with

invoke GetEnviromentVariable, lpName, lpBuffer, nSize

or

push    nSize
        push    lpBuffer
        push    lpName
        call      GetEnvironmentVariable

You don't need line 18 or line 25 as getenv only takes one argument, that being a string pointer.

I generally like using kernel32 library functions and in this case may work for you

GetEnvironmentVariable

The GetEnvironmentVariable function retrieves the value of the specified variable from the environment block of the calling process. The value is in the form of a null-terminated string of characters.

DWORD GetEnvironmentVariable(
LPCTSTR lpName, // address of environment variable name
LPTSTR lpBuffer, // address of buffer for variable value
DWORD nSize // size of buffer, in characters
);

Line 26 would be replaced with

invoke GetEnviromentVariable, lpName, lpBuffer, nSize

or

push    nSize
        push    lpBuffer
        push    lpName
        call      GetEnvironmentVariable

Thank you so much, GetEnvironmentVariable solved my problem.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.