Ghidra is renaming EAX
as param_1
. Why is this happening? I find it very confusing since it is clearly not a parameter and different uses of EAX
are named as if they held the same value.

- 319
- 2
- 12
2 Answers
This is a feature that can be deactivated by unticking the option Markup Register Variable Reference
found in the Edit -> Tool Options
window in the pane Options -> Listing Fields -> Operands Field
.
I would personally not turn this off, because I suspect the proper way to resolve this is to get Ghidra to recognize the local variables the eax
usages present, which will then be renamed accordingly. This should only require some minor cleanup of the decompiled code, possibly even just by using Commit Local Names
, which is found in the context menu of the decompiler window.

- 1,444
- 6
- 22
Ghidra renamed EAX as param_1
because it is a parameter for the current function. This calling convention is similar to fastcall
, although not quite the same. Selecting how to pass arguments to functions is up to the compiler, so long as the code belong to the same program.
At the beginning of your code, param_1
(EAX) contains a pointer to a OLECHAR
object. Later, it is saved to local_8
.
@2af4 MOV param_1,EDI
. This sets the first parameter to the next call, @2af6.
Because EAX is used as parameter for many other functions inside your code, it may be correct to name it param_x
even when the value is clearly not the same. On 2b04, the saved original parameter is loaded into EAX, again, being the first parameter for the next call.
Personally, I like to use register names and not renaming them, but what you see here does make sense.
Edit: You can see that when calling external functions, like FindResourceW
the calling convention changes and param_1
is now on the stack. This is where it is shown in Green rather than Yellow.

- 1,207
- 6
- 19
-
The issue is that renaming the first argument of the function that is shown, will rename all occurrences of
param_1
. At2b13
I would expectparam_1
to be the return value ofFindResourceW
. Why do you think it is the originalparam_1
on the stack? My understanding of the color is that greens are the reads that directly depend on the variable that is written at the occurrence that was clicked on. – Florian Magin Apr 15 '20 at 14:39 -
FindResourceW
returns a value in EAX and right after the call there is amov EBX,param_1
. It would be safe to assume that is is EAX. Right after that EBX (with the return value) is pushed on to the stack and becomesparam_1
for the next function. The last call in this code is again an internal function withparam_1
in EAX and it is also Yellow again. – Yotamz Apr 15 '20 at 14:56 -
1I am fairly sure that you are mistaken. Your assumption seems to be that
param_1
means that it is the first parameter to various functions. This not the case, because if you rename the first argument of the functionFUN_00402ad0
fromparam_1
tofoo
all the occurrences ofparam_1
will be replaced withfoo
. – Florian Magin Apr 15 '20 at 15:31 -
1Your assumption about the meaning of the color is also mistaken (and thus I assume just speculation?). Under
Options -> Listing Fields -> Cursor Text Highlight
is an option forScoped Read Highlight Color
. If you change this, the color of those highlights will change from green to whatever you selected. Which proves my point that this is dataflow analysis that marks the reads from that register and has nothing to do with the variable being currently stored on the stack or in a register. – Florian Magin Apr 15 '20 at 15:35 -
I think you both are right in some of your comments: param_1 is used as a replacement for EAX, regardless of anything. It can be renamed to "foo" and it will be changed at every location. Colours are marked in blocks of usage, so they change as soon as the value is written.
MOV EBX, param_1; MOV ECX, param_1
will have same colour, but thenMOV param_1, xx
will start a new colour block. The colour does not mark the "same" variable.param_1
read before aCALL
can be identified with the same colour as aparam_1
read after theCALL
, and they are clearly not the same thing. – user1156544 Apr 15 '20 at 16:03 -
I guess I got the color thing all wrong, thanks. If you rename one instance of a register (eax) to anything ("foo") it will also rename all other occurrences. I focused on the assumption of the original question that "EAX is clearly not a parameter" and answered that it is a parameter in the calling convention that is in use throughout this function and probably the rest of the program, so the name Ghidra gave it is correct. Looking again, the
param_1
(EAX) is changed 4 times, remaining Yellow and only changes later. – Yotamz Apr 15 '20 at 16:06 -
But the yellows are only valid in the context of the greens. The greens mark a block in which
param_1
is read and not written to. So if I click on theparam_1
of2aee
then this one and2af1
become green but the write at2af4
makes it yellow again. – user1156544 Apr 15 '20 at 16:28 -
I also think the name given is right, but I have second thoughts since registers are used for many things, not like local variables in the stack. So EBP+8 makes sense to be renamed, as it is supposed to hold the same thing, the same "variable". However, EAX sometimes holds one thing (a parameter), then another (a return value), then another (a second return value).... – user1156544 Apr 15 '20 at 16:31
-
The dark yellow is the the location the value is written. Selecting
param_1
at2b0c
should leave the colors the same.The bright yellow has a completely different unrelated meaning. It simply shows every occurrence of that string.
I think they are also marked green if the value is read even if it is written in that instruction. At least I have an ARM binary open right now with an
– Florian Magin Apr 15 '20 at 17:00orr r0,r2
wherer0
is colored green and the position at which itr0
was last written is colored dark yellow. -
This leaves the issue that after
2b07
and2b0e
eax
should have an unrelated value because it is overwritten by the return value of the function calls. I think this is because the dataflow analysis is only local to the function and doesn't have the information that the calls return something ineax
and overwrite any previous value. I suspect this is not the case anymore after the function signatures and parameters of those functions are corrected and commited. – Florian Magin Apr 15 '20 at 17:02
Commit Local Names
seems the correct way, however it is a bit confusing. After applying the option, EAX is renamed:CALL xxx; MOV EBX ,hModule
. ThishModule
suddenly appears "out of the blue", whereas if it wasEAX
it was obvious that was the value returned by theCALL
.hModule
could be a different value defined before theCALL
, it is not obvious it came from the returned value. – user1156544 Apr 15 '20 at 16:13EAX
toparam_1
just as long as it is not changed by aCALL
. Then,EAX
is not reallyparam_1
anymore. – user1156544 Apr 15 '20 at 16:33hModule
because this is the return type of the call and thus also used for the local variable that holds the return value? There should be a local variablehModule
in the decompiler view, try renaming that. If this is a local variable that is reused but actually has a different meaning read https://reverseengineering.stackexchange.com/questions/21236/ghidra-rename-variable-below-current-line/23516#23516 and split out the variable into a new one – Florian Magin Apr 15 '20 at 16:45