I have written the following basic program to add in two numbers, 1+2
, as follows:
.globl main
main:
# put 1 (1 byte int/char) into accumulator register
mov $1, %eax
# add 2 (1 byte int/char), storing result in accumulator
add $2, %eax
# move the result of the accumulator into Data register (input/output)
mov %eax, %edx
ret
When compiled, this does return the expected output:
$ gcc d.s -o d2.out && ./d2.out; echo $?
3
I have a few questions about this program:
globl
function such as main
, or can it ever, for example, remove the main
/ .globl main
parts and just "run the code line-by-line"?Python docs
, where I can just bookmark one page and look everything up there.Is this more-or-less an OK program, or am I misusing any of the operations, etc.?
For a start, yes.
However, assembly is all about efficiency so the last statement is unnecessary:
mov %eax, %edx
Does an assembly file always have to have one globl function such as main
Not necessarily. It can be some other function that you can call from your C/C++ code for example. But if you want to make an executable out of it, you will need main
or _start
if you are using ld
as your linker.
"run the code line-by-line"?
You need a debugger for this. And this will be the most important thing if you want to learn assembly. You will want to look at the registers, see how the values are changing, what is happening to the flags etc. I gave an answer which explains a little bit on how to set up a debugger and step through your code. You will need -g
flag when assembling with gcc
to debug your code.
A basic example:
-g
gcc -g file.s -o file
tui
mode.> gdb --tui ./file
> start # this will automatically start the program and break at main:
> layout regs # show registers at the top (you will need this a lot)
> n # next instruction
> si # step into, when you use functions, si into function
Pressing enter in gdb will automatically execute the last command again. This will save your from typing n
over and over again. Some more commands:
> b 2 # break at line 2
> b func # break at label func
> b main # break at main
> print/x $eax # print value in eax in hex form, there are other /format specifiers, print/d (decimal), print/s string, print/t (binary)
> x/s $eax # print string pointed to by eax
> info frame # look at the current stack frame
These are the most common instructions that you will need. You can type help command_name
to get more info about commands. And there are various cheat sheats etc to help you with this.
You can get a gui as well if you want, personally I don't like them much. Checkout Nemiver, which is pretty good. gdbgui
can be setup using pip
but it's not really good for debugging asm as watching the registers is a pain. There is ddd
which I like most, but it's gui is from the 1970's so ...
Finally, what is the best resource for looking up the ops codes?
The best resource are Intel Manuals, however they might be a bit too difficult to read if you are just starting out. I would recommend Felix Cloutier's x86 asm reference. There's a lot of information and reference things in the x86
tag wiki.
You may also want to read Calling Conventions for Linux and lookup Linux Syscalls which you will be needing quite a lot. If you are going to program or just want to learn more about computers, I would highly recommend reading the Programming from the Ground Up book, which is freely available and uses the AT&T style assembly. It is however a bit dated, so you will have to google things. It has an appendix with common x86 instructions which will be very helpful.