patterncppModerate
x64 assembly clearmem / zeromem
Viewed 0 times
assemblyclearmemx64zeromem
Problem
I've just started learning assembly yesterday, and the first useful thing I've written is a
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
Intel x64 Assembly - on Windows
Example usage in C++
Output of C++ program
Odd Behavior
If I change all of the registers and variables to their 4 byte equivalent (e.g.
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
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
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(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
// ...
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, zlen);
clearmem(&z, sizeof(z));
std::cout (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,0Odd 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
Solution
-
The comments in the
Specifically, the lines that describe the C++ code don't quite reflect on the assembly code.
-
Since it appears the
You can then call
-
I'm not sure how
-
The comments in the
clearmem procedure for the Linux block look a bit confusing. You could just have a summary of the procedure commented above, and have the individual comments for each line specify the meaning of the assembly instructions.Specifically, the lines that describe the C++ code don't quite reflect on the assembly code.
clearmem itself doesn't take two arguments. The for loop comment statement doesn't seem needed, and it may be clearer to specify when the loop should exit. You also don't need the obvious comment for ret.-
Since it appears the
extern "C" corresponds to clearmem, I assume everything else can fully utilize C++. If so, I'd use std::vector in place of the C-style arrays. However, since clearmem performs pointer arithmetic, you should use std::vector::data() to pass in the underlying dynamic array.You can then call
size() for the vector object in main() instead of using sizeof. This function returns an std::size_type, specifically std::vector::size_type.-
I'm not sure how
print_array() is implemented, but I assume it just uses a for loop to print the array elements. You might also not need the template argument, and with just a vector, you'll have just one argument. In the function's loop, you should then use const_iterators for displaying the elements, although using indices is okay (but iterators are still preferred).-
clearmem should take size_t instead of long; the former is the same type returned by the sizeof operator.Context
StackExchange Code Review Q#25830, answer score: 14
Revisions (0)
No revisions yet.