I currently trying to learn assembly language. But I'm stuck.
Suppose I have this C code:
for ( int i = 100; i > 0; i-- ) {
// Some code
}
Now I want to do the same in assembly language. I tried it like this:
__asm__ ("movq $100, %rax;"
".loop:"
//Some code
"decq %rax;"
"cmpq $0, (%rax);"
"jnz .loop;"
);
Compile and run results in a seg fault. It does not seg fault if I remove the cmpq line. But then of course the program will not terminate.
So basically my question is what am I doing wrong here?
cmpq $0, (%rax)
This instruction will try to read memory at the address in rax.
rax will be 99 the first time. Address 99 is not mapped in, so your program segfaults.
You are intending to compare the value in rax to 0, so remove the parentheses.
cmpq $0, %rax
The following instruction:
cmpq $0, (%rax)
is accessing the memory address specified by the rax register, whose value is 99.
The first memory page is not mapped. That memory address, 99, belongs to the first memory page. Therefore, the access above results in a segmentation fault.
You don't want the indirection, instead you want:
cmpq $0, %rax
That is, you want to compare against the contents of rax, not the contents at the memory address specified by rax.
Consider however optimizing the cmp instruction away:
decq %rax is immediately preceding the cmp $0, %rax instruction, which sets ZF if rax is zero. The conditional jump is then performed based on the state of the ZF flag:
decq %rax
cmpq $0, %rax
jnz .loop
The dec instruction affects the ZF flag (as cmp does), so if decrementing rax results in zero, ZF will be set. You can take advantage of that fact and place jnz directly after dec. You don't need cmp at all:
decq %rax
jnz .loop
Remove parenthesis from %rax to get the value of rax. Adding the parenthesis basically tells the assembler, "hey! rax holds an address, please return the contents in that address".
Therefore,
cmpq $0, %rax
is what you need to do.
Related
I have written a Assembly program to display the factorial of a number following AT&T syntax. But it's not working. Here is my code
.text
.globl _start
_start:
movq $5,%rcx
movq $5,%rax
Repeat: #function to calculate factorial
decq %rcx
cmp $0,%rcx
je print
imul %rcx,%rax
cmp $1,%rcx
jne Repeat
# Now result of factorial stored in rax
print:
xorq %rsi, %rsi
# function to print integer result digit by digit by pushing in
#stack
loop:
movq $0, %rdx
movq $10, %rbx
divq %rbx
addq $48, %rdx
pushq %rdx
incq %rsi
cmpq $0, %rax
jz next
jmp loop
next:
cmpq $0, %rsi
jz bye
popq %rcx
decq %rsi
movq $4, %rax
movq $1, %rbx
movq $1, %rdx
int $0x80
addq $4, %rsp
jmp next
bye:
movq $1,%rax
movq $0, %rbx
int $0x80
.data
num : .byte 5
This program is printing nothing, I also used gdb to visualize it work fine until loop function but when it comes in next some random value start entering in various register. Help me to debug so that it could print factorial.
As #ped7g points out, you're doing several things wrong: using the int 0x80 32-bit ABI in 64-bit code, and passing character values instead of pointers to the write() system call.
Here's how to print an integer in x8-64 Linux, the simple and somewhat-efficient1 way, using the same repeated division / modulo by 10.
System calls are expensive (probably thousands of cycles for write(1, buf, 1)), and doing a syscall inside the loop steps on registers so it's inconvenient and clunky as well as inefficient. We should write the characters into a small buffer, in printing order (most-significant digit at the lowest address), and make a single write() system call on that.
But then we need a buffer. The maximum length of a 64-bit integer is only 20 decimal digits, so we can just use some stack space. In x86-64 Linux, we can use stack space below RSP (up to 128B) without "reserving" it by modifying RSP. This is called the red-zone. If you wanted to pass the buffer to another function instead of a syscall, you would have to reserve space with sub $24, %rsp or something.
Instead of hard-coding system-call numbers, using GAS makes it easy to use the constants defined in .h files. Note the mov $__NR_write, %eax near the end of the function. The x86-64 SystemV ABI passes system-call arguments in similar registers to the function-calling convention. (So it's totally different from the 32-bit int 0x80 ABI, which you shouldn't use in 64-bit code.)
// building with gcc foo.S will use CPP before GAS so we can use headers
#include <asm/unistd.h> // This is a standard Linux / glibc header file
// includes unistd_64.h or unistd_32.h depending on current mode
// Contains only #define constants (no C prototypes) so we can include it from asm without syntax errors.
.p2align 4
.globl print_integer #void print_uint64(uint64_t value)
print_uint64:
lea -1(%rsp), %rsi # We use the 128B red-zone as a buffer to hold the string
# a 64-bit integer is at most 20 digits long in base 10, so it fits.
movb $'\n', (%rsi) # store the trailing newline byte. (Right below the return address).
# If you need a null-terminated string, leave an extra byte of room and store '\n\0'. Or push $'\n'
mov $10, %ecx # same as mov $10, %rcx but 2 bytes shorter
# note that newline (\n) has ASCII code 10, so we could actually have stored the newline with movb %cl, (%rsi) to save code size.
mov %rdi, %rax # function arg arrives in RDI; we need it in RAX for div
.Ltoascii_digit: # do{
xor %edx, %edx
div %rcx # rax = rdx:rax / 10. rdx = remainder
# store digits in MSD-first printing order, working backwards from the end of the string
add $'0', %edx # integer to ASCII. %dl would work, too, since we know this is 0-9
dec %rsi
mov %dl, (%rsi) # *--p = (value%10) + '0';
test %rax, %rax
jnz .Ltoascii_digit # } while(value != 0)
# If we used a loop-counter to print a fixed number of digits, we would get leading zeros
# The do{}while() loop structure means the loop runs at least once, so we get "0\n" for input=0
# Then print the whole string with one system call
mov $__NR_write, %eax # call number from asm/unistd_64.h
mov $1, %edi # fd=1
# %rsi = start of the buffer
mov %rsp, %rdx
sub %rsi, %rdx # length = one_past_end - start
syscall # write(fd=1 /*rdi*/, buf /*rsi*/, length /*rdx*/); 64-bit ABI
# rax = return value (or -errno)
# rcx and r11 = garbage (destroyed by syscall/sysret)
# all other registers = unmodified (saved/restored by the kernel)
# we don't need to restore any registers, and we didn't modify RSP.
ret
To test this function, I put this in the same file to call it and exit:
.p2align 4
.globl _start
_start:
mov $10120123425329922, %rdi
# mov $0, %edi # Yes, it does work with input = 0
call print_uint64
xor %edi, %edi
mov $__NR_exit, %eax
syscall # sys_exit(0)
I built this into a static binary (with no libc):
$ gcc -Wall -static -nostdlib print-integer.S && ./a.out
10120123425329922
$ strace ./a.out > /dev/null
execve("./a.out", ["./a.out"], 0x7fffcb097340 /* 51 vars */) = 0
write(1, "10120123425329922\n", 18) = 18
exit(0) = ?
+++ exited with 0 +++
$ file ./a.out
./a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=69b865d1e535d5b174004ce08736e78fade37d84, not stripped
Footnote 1: See Why does GCC use multiplication by a strange number in implementing integer division? for avoiding div r64 for division by 10, because that's very slow (21 to 83 cycles on Intel Skylake). A multiplicative inverse would make this function actually efficient, not just "somewhat". (But of course there'd still be room for optimizations...)
Related: Linux x86-32 extended-precision loop that prints 9 decimal digits from each 32-bit "limb": see .toascii_digit: in my Extreme Fibonacci code-golf answer. It's optimized for code-size (even at the expense of speed), but well-commented.
It uses div like you do, because that's smaller than using a fast multiplicative inverse). It uses loop for the outer loop (over multiple integer for extended precision), again for code-size at the cost of speed.
It uses the 32-bit int 0x80 ABI, and prints into a buffer that was holding the "old" Fibonacci value, not the current.
Another way to get efficient asm is from a C compiler. For just the loop over digits, look at what gcc or clang produce for this C source (which is basically what the asm is doing). The Godbolt Compiler explorer makes it easy to try with different options and different compiler versions.
See gcc7.2 -O3 asm output which is nearly a drop-in replacement for the loop in print_uint64 (because I chose the args to go in the same registers):
void itoa_end(unsigned long val, char *p_end) {
const unsigned base = 10;
do {
*--p_end = (val % base) + '0';
val /= base;
} while(val);
// write(1, p_end, orig-current);
}
I tested performance on a Skylake i7-6700k by commenting out the syscall instruction and putting a repeat loop around the function call. The version with mul %rcx / shr $3, %rdx is about 5 times faster than the version with div %rcx for storing a long number-string (10120123425329922) into a buffer. The div version ran at 0.25 instructions per clock, while the mul version ran at 2.65 instructions per clock (although requiring many more instructions).
It might be worth unrolling by 2, and doing a divide by 100 and splitting up the remainder of that into 2 digits. That would give a lot better instruction-level parallelism, in case the simpler version bottlenecks on mul + shr latency. The chain of multiply/shift operations that brings val to zero would be half as long, with more work in each short independent dependency chain to handle a 0-99 remainder.
Related:
NASM version of this answer, for x86-64 or i386 Linux How do I print an integer in Assembly Level Programming without printf from the c library?
How to convert a binary integer number to a hex string? - Base 16 is a power of 2, conversion is much simpler and doesn't require div.
Several things:
0) I guess this is 64b linux environment, but you should have stated so (if it is not, some of my points will be invalid)
1) int 0x80 is 32b call, but you are using 64b registers, so you should use syscall (and different arguments)
2) int 0x80, eax=4 requires the ecx to contain address of memory, where the content is stored, while you give it the ASCII character in ecx = illegal memory access (the first call should return error, i.e. eax is negative value). Or using strace <your binary> should reveal the wrong arguments + error returned.
3) why addq $4, %rsp? Makes no sense to me, you are damaging rsp, so the next pop rcx will pop wrong value, and in the end you will run way "up" into the stack.
... maybe some more, I didn't debug it, this list is just by reading the source (so I may be even wrong about something, although that would be rare).
BTW your code is working. It just doesn't do what you expected. But work fine, precisely as the CPU is designed and precisely what you wrote in the code. Whether that does achieve what you wanted, or makes sense, that's different topic, but don't blame the HW or assembler.
... I can do a quick guess how the routine may be fixed (just partial hack-fix, still needs rewrite for syscall under 64b linux):
next:
cmpq $0, %rsi
jz bye
movq %rsp,%rcx ; make ecx to point to stack memory (with stored char)
; this will work if you are lucky enough that rsp fits into 32b
; if it is beyond 4GiB logical address, then you have bad luck (syscall needed)
decq %rsi
movq $4, %rax
movq $1, %rbx
movq $1, %rdx
int $0x80
addq $8, %rsp ; now rsp += 8; is needed, because there's no POP
jmp next
Again didn't try myself, just writing it from head, so let me know how it changed situation.
I am getting a segfault at the movq (%rsi, %rcx) line.
I know you can't do mem->mem mov, so I did it through a temporary register. (%rsi), %rcx, then in the loop %rcx, (%rdi). Here is my code:
experimentMemset: #memset(void *ptr, int value, size_t num)
#%rdi #%rsi #%rdx
movq %rdi, %rax #sets rax to the first pointer, to return later
.loop:
cmp $0, (%rdx) #see if num has reached 0
je .end
cmpb $0, (%rdi) #see if string has ended also
je .end
movq %rsi, %rdi #copies value into rdi
inc %rdi #increments pointer to traverse string
dec %rdx #decrements the count, aka num
jmp .loop
.end:
ret
As you discovered, RDX holds a size (an integer count), not a pointer. It's passed by value, not by reference.
cmp $0, (%rdx)
compares not the register, but the location pointed by it. It seems that %rdx is used as a counter, so you should compare the register itself.
test %rdx,%rdx ; je count_was_zero
There are other bugs, like checking the contents of the write-only destination for zeros, and not storing %sil into (%rdi). But this was the cause of the segfault in the current version of the question.
This is a homework question.
I am attempting to obtain information from the following assembly code (x86 linux machine, compiled with gcc -O2 optimization). I have commented each section to show what I know. A big chunk of my assumptions could be wrong, but I have done enough searching to the point where I know I should ask these questions here.
.section .rodata.str1.1,"aMS",#progbits,1
.LC0:
.string "result %lx\n" //Printed string at end of program
.text
main:
.LFB13:
xorl %esi, %esi // value of esi = 0; x
movl $1, %ecx // value of ecx = 1; result
xorl %edx, %edx // value of edx = 0; Loop increment variable (possibly mask?)
.L2:
movq %rcx, %rax // value of rax = 1; ?
addl $1, %edx // value of edx = 1; Increment loop by one;
salq $3, %rcx // value of rcx = 8; Shift left rcx;
andl $3735928559, %eax // value of eax = 1; Value AND 1 = 1;
orq %rax, %rsi // value of rsi = 1; 1 OR 0 = 1;
cmpl $22, %edx // edx != 22
jne .L2 // if true, go back to .L2 (loop again)
movl $.LC0, %edi // Point to string
xorl %eax, %eax // value of eax = 0;
jmp printf // print
.LFE13: ret // return
And I am supposed to turn it into the following C code with the blanks filled in
#include <stdio.h>
int main()
{
long x = 0x________;
long result = ______;
long mask;
for (mask = _________; mask _______; mask = ________) {
result |= ________;
}
printf("result %lx\n",result);
}
I have a couple of questions and sanity checks that I want to make sure I am getting right since none of the similar examples I have found are for optimized code. Upon compiling some trials myself I get something close but the middle part of L2 is always off.
MY UNDERSTANDING
At the beginning, esi is xor'd with itself, resulting in 0 which is represented by x. 1 is then added to ecx, which would be represented by the variable result.
x = 0; result = 1;
Then, I believe a loop increment variable is stored in edx and set to 0. This will be used in the third part of the for loop (update expression). I also think that this variable must be mask, because later on 1 is added to edx, signifying a loop increment (mask = mask++), along with edx being compared in the middle part of the for loop (test expression aka mask != 22).
mask = 0; (in a way)
The loop is then entered, with rax being set to 1. I don't understand where this is used at all since there is no fourth variable I have declared, although it shows up later to be anded and zeroed out .
movq %rcx, %rax;
The loop variable is then incremented by one
addl $1, %edx;
THE NEXT PART MAKES THE LEAST AMOUNT OF SENSE TO ME
The next three operations I feel make up the body expression of the loop, however I have no idea what to do with them. It would result in something similar to result |= x ... but I don't know what else
salq $3, %rcx
andl $3735928559, %eax
orq %rax, %rsi
The rest I feel I have a good grasp on. A comparison is made ( if mask != 22, loop again), and the results are printed.
PROBLEMS I AM HAVING
I don't understand a couple of things.
1) I don't understand how to figure out my variables. There seem to be 3 hardcoded ones along with one increment or temporary storage variable that is found in the assembly (rax, rcx, rdx, rsi). I think rsi would be the x , and rcx would be result, yet I am unsure of if mask would be rdx or rax, and either way, what would the last variable be?
2) What do the 3 expressions of which I am unsure of do? I feel that I have them mixed up with the incrementation somehow, but without knowing the variables I don't know how to go about solving this.
Any and all help will be great, thank you!
The answer is :
#include <stdio.h>
int main()
{
long x = 0xDEADBEEF;
long result = 0;
long mask;
for (mask = 1; mask != 0; mask = mask << 3) {
result |= mask & x;
}
printf("result %lx\n",result);
}
In the assembly :
rsi is result. We deduce that because it is the only value that get ORed, and it is the second argument of the printf (In x64 linux, arguments are stored in rdi, rsi, rdx, and some others, in order).
x is a constant that is set to 0xDEADBEEF. This is not deductible for sure, but it makes sense because it seems to be set as a constant in the C code, and doesn't seem to be set after that.
Now for the rest, it is obfuscated by an anti-optimization by GCC. You see, GCC detected that the loop would be executed exactly 21 times, and thought is was clever to mangle the condition and replace it by a useless counter. Knowing that, we see that edx is the useless counter, and rcx is mask. We can then deduce the real condition and the real "increment" operation. We can see the <<= 3 in the assembly, and notice that if you shift left a 64-bit int 22 times, it becomes 0 ( shift 3, 22 times means shift 66 bits, so it is all shifted out).
This anti-optimization is sadly really common for GCC. The assembly can be replaced with :
.LFB13:
xorl %esi, %esi
movl $1, %ecx
.L2:
movq %rcx, %rax
andl $3735928559, %eax
orq %rax, %rsi
salq $3, %rcx // implicit test for 0
jne .L2
movl $.LC0, %edi
xorl %eax, %eax
jmp printf
It does exactly the same thing, but we removed the useless counter and saved 3 assembly instructions. It also matches the C code better.
Let's work backwards a bit. We know that result must be the second argument to printf(). In the x86_64 calling convention, that's %rsi. The loop is everything between the .L2 label and the jne .L2 instruction. We see in the template that there's a result |= line at the end of the loop, and indeed, there's an orl instruction there with %rsi as its target, so that checks out. We can now see what it's initialized to at the top of .main.
ElderBug is correct that the compiler spuriously optimized by adding a counter. But we can still figure out: which instruction runs immediately after the |= when the loop repeats? That must be the third part of the loop. What runs immediately before the body of the loop? That must be the loop initialization. Unfortunately, you'll have to figure out what would have happened on the 22nd iteration of the original loop to reverse-engineer the loop condition. (But sal is a left-shift, and that line is a vestige of the original loop condition, which would have been followed by a conditional branch before the %rdx test was inserted.)
Note that the code keeps a copy of the value of mask around in %rcx before modifying it in %rax, and x is folded into a constant (take a close look at the andl line).
Also note that you can feed the .S file to gas to get a .o and see what it does.
I have this loop that essentially adds two dynamic-width integers (in reality, it is unrolled a bit, but that does not matter here). Register RCX contains the destination address, RDX contains the source address, and R8 contains the length of the arrays.
clc # Clear CF flag before beginning
.Lloop0:
movq (%rdx), %rax # Load memory for next addition
adcq %rax, (%rcx) # Perform addition with carry (i.e. using CF flag)
leaq 8(%rcx), %rcx # Increment destination address (without affecting CF)
leaq 8(%rdx), %rdx # Increment source address (without affecting CF)
leaq -1(%r8), %r8 # Decrement length (without affecting CF)
testq %r8, %r8 # Test if length is zero (affects CF!)
jne Lloop0
The problem is that the TEST instruction clears the CF flag, which is needed by the next ADC. The CMP instruction would also have a similar effect.
I could of course copy the FLAGS register using LAHF before the test and restore it using SAHF at the beginning of the loop, but I would like to avoid that if there is a way around it.
You can swap the roles of %r8 and %rcx above to yield:
clc
.p2align 4 # just a thought...
.Lloop0:
jrcxz .Lloop0_end
...
leaq -1(%rcx), %rcx
jmp .Lloop0
.Lloop0_end:
I was looking at the Compiler output for a C program, just for academic purposes and happened to get the following output.
.file "test.c"
.section .rodata
.LC0:
.string "Hello World"
.text
.globl main
.type main, #function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
.section .note.GNU-stack,"",#progbits
I understand the parts where the based pointer and stack pointer operations are taking place and other operation, I wanted to know what is the use of putting
movl $.LC0, %edi
how is loading the address of the test "Hello world" from the data block into the destination register solving the purpose, we could have just loaded that address in the accumulator and let printf handle it. I am not used to programming in assembly but i can make out what the program is doing, am i missing something obvious here?
Google searches showed that they were used for string operations but none said why?
First of all, your call on printf may be passing arguments by registers and not by stack because it was optimised in that way, or because its attributes during compilation were set to __fastcall (MSVC) or __attribute__((fastcall)).
%esi and %esi registers are used in string operations because of their meaning to string instructions, such as cmps, lods, movs, scas, stos, outs or ins. These instructions use the destination and source register for quick sequential access to a string of bytes/words/doublewords. They can be used in loops to make simple operations that are known to be performed continuously in memory, and can shorter execution time in combination with loop prefixes by removing the need of pointer manipulation and limit checking.
A very good example on this is the movs instruction (it also has another forms as movsb, movsw, movsd). If you wanted to write a simple string copy procedure without string instruction, you write something like this:
; IN: EAX=source&, EBX=dest&, ECX=count
; OUT: nothing
copy:
.loop:
cmp ecx, 0
jz .end
dec ecx
mov al, byte [eax+ecx]
mov byte [ebx+ecx], al
jmp .loop
.end:
ret
movsb instruction copies [esi] to [edi], increments esi and edi, then decrements ecx. With this in mind you can write somethign similar to this:
; IN: ESI=source&, EDI=dest&, ECX=count
; OUT: nothing
copy:
.loop:
jecxz .end
movsb
jmp .loop
.end:
ret
Using loop prefixes, you can again speed the whole operation
; IN: ESI=source&, EDI=dest&, ECX=count
; OUT: nothing
copy:
rep movsb
ret
I am going to say yes and no to user35443 answer.
I wanted to know what is the use of putting
movl $.LC0, %edi
Since you are using 64bit Linux (from the use of rbp), in 64 bit land, parameters are passed in registers. rdi contains the first parameter, rsi the second, rdx 3rd, rcx 4th, r8 5th, r9 the 6th parameter; any more parameters are passed on the stack.
we could have just loaded that address in the accumulator and let
printf handle it
No! When using Assembly, it is up to you to read and understand the ABI for the OS you are using and follow it to the T! If you were using Windows, the first parameter would be in rcx instead. It has nothing to do with the source nor destination.
the "Accumulator" is actually a parameter to printf and all vararg functions really. r/eax contains the number of floating point numbers passed in the xmm registers, since in your example code no floats are passed, eax is set to 0.