I have an ASM file written for X64. It provides a leaf function. The file was assembled with MASM64/ML64.
The C-pseduo code with a signature is:
int GenerateBlock(byte* ptr, size_t size, unsigned int safety)
{
if (ptr == NUL) return 0; /*FAIL*/
...
}
Here's the same portion of ASM code:
;; RCX (in): byte* buffer
;; RDX (in): size_t bsize
;; R8d (in): unsigned int safety
;; RAX (out): bool, success (1), failure (0)
ASM_GenerateBlock PROC buffer:QWORD,bsize:QWORD,safety:DWORD
LOCAL val:QWORD ;; local variables
MWSIZE EQU 8 ;; machine word size
;; Validate pointer
cmp buffer, 0
je ASM_GenerateBlock_Cleanup
;; Cleanup will set RAX to 0 and return
...
ENDP
When I step the call, it appears fastcall
is being used, which is consistent with the docs. The first two args are showing up in RCX
and RDX
, which is also consistent.
But a test case with a NULL
pointer is producing unexpected results. Here's the test case that's being used:
ASM_GenerateBlock(NULL /*ptr*/, 64 /*size*/, 20 /*safety*/);
When I step the code, RCX
appears to be buffer
(its NULL
), RDX
appears to be bsize
(its 0x40
), but the compare cmp buffer, 0
is occurring against a value that unknown to me. From the immediate window:
buffer
0x000000013f82bcd0
*(__int64*)buffer
0x000000013f62aba8
bsize
0x000000013f14871b
*(__int64*)bsize
0xccccccc348c48348
13f82bcd0
looks roughly like an instruction pointer address (EIP is 13F50D268
). Its does not appear to be similar to ESP
or EBP
.
I have a few questions...
- What addressing mode is ML64 using for the variable
buffer
? - Where is the value of the variable
buffer
coming from? - Why is
ML64
not usingECX
for the variablebuffer
? - How can I fix this?
The same code, shortened to 32-bits, assembles and executes fine. However, ML puts buffer
and bsize
on the stack and addresses them relative to EBP
.
I also tried changing to cmp QWORD PTR buffer, 0
, but it did not help.