I'm trying to figure out what this block of assembly code is doing:
mystery:
.LFB0
testl %edi, %edi
je .L3
subq $8, %rsp
shrl $2, %edi
call mystery
addq $1, %rax
jmp .L2
.L3:
movl $l, %eax
ret
.L2:
addq $8, %rsp
ret
So far I have this as the C code:
long mystery(unsigned n){
if(n==0)
return 1;
And I get that there is a recursive function going on here while n!=0 but I don't understand what the %rsp register is doing
Here's my guess:
#include <inttypes.h>
int64_t mystery(int32_t n) {
if (n == 0) {
return 1;
}
return 1 + mystery(n / 4);
}
I don't know what the $l is in the line:
movl $l, %eax
so my above solution assumes it's a typo for $1. Enlighten me.
Related
This is more an academic exercise than anything else, but I'm looking to write a recursive function in assembly, that, if it receives and "interrupt signal" it returns to the main function, and not just the function that invoked it (which is usually the same recursive function).
For this test, I'm doing a basic countdown and printing one-character digits (8...7...6...etc.). To simulate an "interrupt", I am using the number 7, so when the function hits 7 (if it starts above that), it will return a 1 meaning it was interrupted, and if it wasn't interrupted, it'll countdown to zero. Here is what I have thus far:
.globl _start
_start:
# countdown(9);
mov $8, %rdi
call countdown
# return 0;
mov %eax, %edi
mov $60, %eax
syscall
print:
push %rbp
mov %rsp, %rbp
# write the value to a memory location
pushq %rdi # now 16-byte aligned
add $'0', -8(%rbp)
movb $'\n', -7(%rbp)
# do a write syscall
mov $1, %rax # linux syscall write
mov $1, %rdi # file descriptor: stdout=1
lea -8(%rbp), %rsi # memory location of string goes in rsi
mov $2, %rdx # length: 1 char + newline
syscall
# restore the stack
pop %rdi
pop %rbp
ret;
countdown:
# this is the handler to call the recursive function so it can
# pass the address to jump back to in an interrupt as one of the
# function parameters
# (%rsp) currntly holds the return address, and let's pass that as the second argument
mov %rdi, %rdi # redundant, but for clarity
mov (%rsp), %rsi # return address to jump
call countdown_recursive
countdown_recursive:
# bool countdown(int n: n<10, return_address)
# ...{
push %rbp
mov %rsp, %rbp
# if (num<0) ... return
cmp $0, %rdi
jz end
# imaginary interrupt on num=7
cmp $7, %rdi
jz fast_ret
# else...printf("%d\n", num);
push %rsi
push %rdi
call print
pop %rdi
pop %rsi
# --num
dec %rdi
# countdown(num)
call countdown_recursive
end:
# ...}
mov $0, %eax
mov %rbp, %rsp
pop %rbp
ret
fast_ret:
mov $1, %eax
jmp *%rsi
Does the above look like a valid approach, passing the memory address I want to go back to in rsi? The function was incredibly tricky for me to write, but I think mainly due to the fact that I'm pretty new/raw with assembly.
As well as returning to this alternate return address, you also need to restore the caller's (call-preserved) registers, not just the ones of your most recent parent. That includes RSP.
You're basically trying to re-invent C's setjmp / longjmp which does exactly this, including resetting the stack pointer back to the scope where you called setjmp. I think a few of the questions in SO's setjmp tag are about about implementing your own setjmp / longjmp in asm.
Also, to make this more efficient you might want to use a custom calling convention where the return address pointer (or a jmpbuf pointer after implementing the above) is in a call-preserved register like R15, so you don't have to save/restore it around print calls inside the body of your recursive function.
I've recently started looking into assembly code and I'm trying to recode some basic system functions to get a grip on it, I'm currently stuck on a segmentation fault at 0x0 on my strchr.
section .text
global strchr
strchr:
xor rax, rax
loop:
cmp BYTE [rdi + rax], 0
jz end
cmp sil, 0
jz end
cmp BYTE [rdi + rax], sil
jz good
inc rax
jmp loop
good:
mov rax, [rdi + rcx]
ret
end:
mov rax, 0
ret
I can't figure out how to debug it using GDB, also the documentation I've came across is pretty limited or hard to understand.
I'm using the following main in C to test
extern char *strchr(const char *s, int c);
int main () {
const char str[] = "random.string";
const char ch = '.';
char *ret;
ret = strchr(str, ch);
printf("%s\n", ret);
printf("String after |%c| is - |%s|\n", ch, ret);
return(0);
}
The Problem
The instruction immediately following the good label:
mov rax, [rdi + rcx]
should actually be:
lea rax, [rdi + rax]
You weren't using rcx at all, but rax and, what you need is the address of that position, not the value at that position (i.e. lea instead of mov).
Some Advice
Note that the typical idiom for comparing sil against zero is actually test sil, sil instead of cmp sil, 0. It would be then:
test sil, sil
jz end
However, if we look at the strchr(3) man page, we can find the following:
char *strchr(const char *s, int c);
The terminating
null byte is considered part of the string, so that if c is specified as '\0', these functions return a pointer to the terminator.
So, if we want this strchr() implementation to behave as described in the man page, the following code must be removed:
cmp sil, 0
jz end
The typical zeroing idiom for the rax register is neither mov rax, 0 nor xor rax, rax, but rather xor eax, eax, since it doesn't have the encode the immediate zero and saves one byte respect to the latter.
With the correction and the advice above, the code would look like the following:
section .text
global strchr
strchr:
xor eax, eax
loop:
; Is end of string?
cmp BYTE [rdi + rax], 0
jz end
; Is matched?
cmp BYTE [rdi + rax], sil
jz good
inc rax
jmp loop
good:
lea rax, [rdi + rax]
ret
end:
xor eax, eax
ret
The C and assembly code:
long pcount_r(unsigned long x) {
if (x == 0) return 0;
else return (x & 1) + pcount_r (x>>1);
}
pcoutn_r:
movl $0, %eax
testq %rdi, %rdi
je .L6
pushq %rbx
movq %rdi, %rbx
andl $1, %ebx
shrq %rdi
call pcount_r
addq %rbx, %rax
popq %rbx
.L6:
rep; ret
If passing function a value x = 5 (binary representation is 0101). Register %rdi is the x value, and %rbx holds x value by "movq %rdi, %rbx" before pass "x>>1" to the next recursive call. Therefore, %rbx holds 0101, then 010, then 01.
The first call of pcount_r:
%rdi %rbx
0101 --> 0101
The second call of pcount_r:
%rdi %rbx
010 --> 010
The third call and etc...
%rbx can only hold one value at the time, To me, it seems just overwriting the previous value of %rbx, rather than saving data on a stack. My question is: how can %rbx restore the previous %rbx value when a recursive call ends?
more details about this function can be found in this link.
Recursive Procedures at time 55:00
I see. My mistake is that I thought register %rbx is holding the x value. But In fact, %rbx is just holding x value temporarily, assembly code "pushq %rbx" pushes %rbx value to the stack before passing the next %rdi to %rbx. Similarly, the value is restored by "popq %rbx".
I am re-writing an encryption/compression library and it seems like it is getting to be a lot of processing per bytes processed. I would prefer to use an enumeration type when choosing which of several limited ways the encryption can go (the proper way), but when those paths become cyclical, I have to add extra code to test for type'last and type'first. I can always just write such a condition in for the type, or assign the addition/subtraction operator on the type a function to wrap around the result, but that is more code and processing that will add up quickly when it has to run every eight bytes along with everything else. Is there a way to make the operation about as efficient as if it were a simple "mod" type, like
type Modular is mod 64 ....;
for ......;
pragma ....;
type Frequency_Counter is array(Modular) of Long_Integer;
Head : Modular := (others => 0);
Freq : Frequency_Counter(Size) := (others => 0);
Encryption_Label : Modular := Hash3;
Block_Sample : Modular := Hash5;
...
Hash3 := Hash3 + 1;
Freq (Hash3):= Freq(Hash3) + 1; -- Here is where my made-on-the-fly example is focused
I think I can make the whole algorithm more efficient and use enumeration types if I can just get the enumeration type to do math in the processor in the same number of cycles as with a mod type math. I have gotten a little creative in thinking of a way, but they were too obviously not right for me to use any of them as an example. The only thing I can think might be possible exceeds my skill, and that is making a procedure using inline ASM (gas assembly language syntax) to make the operation very direct to the processor.
PS: I know this is a minor gain, alone. Any gain is appropriate for the application.
Not sure that it’ll make much difference!
Given this
package Cyclic is
type Enum is (A, B, C, D, E);
type Modular is mod 5;
function Next_Enum (En : Enum) return Enum is
(if En = Enum'Last then Enum'First else Enum'Succ (En)) --'
with Inline_Always;
end Cyclic;
and
with Cyclic; use Cyclic;
procedure Cyclic_Use (N : Natural; E : in out Enum; M : in out Modular) is
begin
begin
for J in 1 .. N loop
E := Next_Enum (E);
end loop;
end;
begin
for J in 1 .. N loop
M := M + 1;
end loop;
end;
end Cyclic_Use;
and compiling using GCC 5.2.0 with -O3 (gnatmake -O3 -c -u -f cyclic_use.adb -cargs -S), the x86_64 assembler generated for the two loops is
(enumeration)
L3:
leal 1(%rsi), %ecx
addl $1, %eax
cmpb $4, %sil
cmove %r8d, %ecx
cmpl %eax, %edi
movl %ecx, %esi
jne L3
(modular)
L4:
leal -4(%rdx), %ecx
addl $1, %eax
cmpb $3, %dl
leal 1(%rdx), %r8d
movl %ecx, %edx
cmovle %r8d, %edx
cmpl %eax, %edi
jne L4
I don’t pretend to know x86_64 assembler, and I don’t know why the enumeration version compares against 4 while the modular version compares against 3, but these look very similar to me! but the enumeration version is one instruction shorter ...
I'm new to x86.
I know what this kind of thing with the pointers means.
*command* %eax, %ebx
But how are these different, and what do they mean?
*command* %eax, (%ebx)
*command* (%eax), %ebx
*command* (%eax, %ebx, 4), %ecx
I think your question is, "what does the parentheses around a register's name mean/do?" At a high level, the parentheses say to perform a load from a memory address in and use that value in the instruction. Ie, whereas
*command* %eax, %ebx
operates on the values in the %eax and %ebx registers directly,
*command* (%eax), (%ebx)
loads the values from memory pointed to by %eax and %ebx and operates on them. There are actually a few more variants of the parentheses than you listed. For a description of them (including the last instruction example that you asked about), check here.
Hope that helps. Feel free to post back if you have any more questions.
Assume the following operations:
movl %eax, (%ebx) [1]
movl (%eax), %ebx [2]
movl (%eax, %ebx, 4), %ecx [3]
1, The first one will copy the value of eax into an address stored in ebx, smiler to this in C:
*(int *)ebx = eax; // copy eax into address
2, The second will copy the value stored in an address at eax into ebx:
ebx = *(int *)eax; // copy what in address into ebx
3, This is an array operation, where ebx is the index and 4 is the size of an element of the array.
ecx = ((int *) p)[ebx];
calculated as:
ecx = *(int *)((char *)p + ebx * sizeof(int));
In AT&T asm syntax, parenthesis mean "dereference" -- roughly the same as the unary * operator in C. So some rough equivalences:
movl %eax, %ebx eax = ebx
movl %eax, (%ebx) eax = *ebx
movl (%eax), %ebx *eax = ebx
That leqaves your last example:
movl (%eax, %ebx, 4), %ecx
In this case, there are multiple values that are combined to form the address to dereference. It's roughly equivalent to
*(eax + ebx*4) = ecx