I've just started learning assembly yesterday, and the first useful thing I've written is a clearmem
function.
I'm looking for general feedback regarding my coding of this function, whether there any flaws with it other than the obvious one of a user passing a value <= 0 to the size
argument, or an invalid pointer to the ptr
argument (should I really even check for that in practical use)?
I also observed an odd behavior that I still don't quite understand, so if you can explain that, then that would be much appreciated as well.
Intel x64 Assembly - on Linux
clearmem: ; void clearmem( void* ptr, long size )
mov rcx, rsi ; copy rsi/size to rcx (aka the counter register)
next: ; for( long i = size; i > 0; i-- )
mov byte [rdi+rcx-1], 0 ; *(reinterpret_cast<char*>(ptr+i-1)) = 0;
loop next ; dec rcx; cmp rcx, 0; jg next
ret ; return
Intel x64 Assembly - on Windows
clearmem proc
xchg rcx, rdx ; swap arg1 and arg2... windows uses rcx for arg1, and rdx for arg2
next:
mov byte ptr[rdx+rcx-1], 0
loop next
ret
clearmem endp
Example usage in C++
#include <iostream>
// ...
extern "C" void clearmem( void* ptr, long size );
// ...
int main( int argc, char* argv[] )
{
int z[] = {1,2,3,4,5,6,7,8,9,10};
int zlen = sizeof(z) / sizeof(int);
std::cout << "z[] before clearmem() = ";
print_array<int>(z, zlen);
clearmem(&z, sizeof(z));
std::cout << "z[] after clearmem() = ";
print_array<int>(z, zlen);
return 0;
}
Output of C++ program
z[] before clearmem() = 1,2,3,4,5,6,7,8,9,10
z[] after clearmem() = 0,0,0,0,0,0,0,0,0,0
Odd Behavior
If I change all of the registers and variables to their 4 byte equivalent (e.g. rcx
-> ecx
, long
-> int
) then it still works fine in Windows, but on Linux it will segfault. I used GDB to set a break point on mov byte[rdi+rcx-1], 0
and used info registers
to see the values in the registers and they were extrmely high. For instance rdi
was 0x00007FFFFFFFE6E0 at the time, and considering I only have 16 GB of RAM, I would have expected a value less than 0x0000000400000000.
What's going on here? Why does this work on Windows, but not on Linux? Note: Obviously, I know I shouldn't do this, but I like breaking things...