<- previous index next ->
See www.csee.umbc.edu/help/nasm/nasm_64.shtml for notes on using debugger.
A program that prints where its sections are allocated
(in virtual memory) is where_64.asm
My output, yours should be different, is
where_64.lst
where_64.out
where_64.dbg
; where_64.asm print addresses of sections
; Assemble: nasm -g -f elf64 -l where_64.lst where_64.asm
; Link: gcc -g3 -m64 -o where_64 where_64.o
; Run: ./where_64 > where_64.out
; Output: you need to run it, results on my computer:
; data a: at ??? waries with computer and software
; bss b: at ???
; rodata c: at ???
; code main: at ???
;
; to debug, typically after segfault
; gdb where_64
; run
; backtrace
; optionally: disassemble x/60x main
; end with q y
extern printf ; the C function, to be called
section .data ; Data section, initialized variables
a: db 0,1,2,3,4,5,6,7
fmt: db "data a: at %lX",10
db "bss b: at %lX",10
db "rodata c: at %lX",10
db "code main: at %lX",10,0
section .bss ; reserved storage, uninitialized
b: resq 8
section .rodata ; read only initialized storage
c: db 7,6,5,4,3,2,1,0
section .text ; Code section.
global main ; the standard gcc entry point
main: ; the program label for the entry point
push rbp
mov rbp,rsp
push rbx ; save callers registers
mov rdi,fmt ; pass address of fmt to printf
lea rsi,[a] ; using load effective address
lea rdx,[b] ; using load effective address
lea rcx,[c] ; using load effective address
lea r8,[main] ; using load effective address
mov rax,0 ; no float
call printf ; Call C function
mov rdi,fmt ; pass address of fmt to printf
mov rsi,a ; just loading address
mov rdx,b ; just loading address
mov rcx,c ; just loading address
mov r8,main ; just loading address
mov rax,0 ; no float
call printf ; Call C function
pop rbx ; restore callers registers
mov rsp,rbp
pop rbp
mov rax,0 ; normal, no error, return value
ret ; return
My output on gl.linux.umbc.edu is where_64.out (my notes added)
data a: at 6008CC .data start
bss b: at 600930 .bss start after .data
rodata c: at 400658 .rodata start after .text
code main: at 4004D0 .text start
data a: at 6008CC
bss b: at 600930
rodata c: at 400658
code main: at 4004D0
To run debugger and look at disassemble and memory dump
gdb where_64 > where_64.dbg
break main
run
disassemble
x/60x main
q
y
A small part of my output from debugger where_64.dbg
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-83.el6)
...
(gdb) break main
Breakpoint 1 at 0x4004d4: file where_64.asm, line 37.
(gdb) run
Starting program: /afs/umbc.edu/users/s/q/squire/home/cs313/where_64
Breakpoint 1, main () at where_64.asm:37
37 push rbx ; save callers registers
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.166.el6_7.3.x86_64
(gdb) disassemble
Dump of assembler code for function main:
0x00000000004004d0 +0: push %rbp
0x00000000004004d1 +1: mov %rsp,%rbp
=> 0x00000000004004d4 +4: push %rbx
0x00000000004004d5 +5: movabs $0x6008d4,%rdi
0x00000000004004df +15: lea 0x6008cc,%rsi
0x00000000004004e7 +23: lea 0x600930,%rdx
0x00000000004004ef +31: lea 0x400658,%rcx
0x00000000004004f7 +39: lea 0x4004d0,%r8
0x00000000004004ff +47: movabs $0x0,%rax
0x0000000000400509 +57: callq 0x4003b8 printf@plt
0x000000000040050e +62: movabs $0x6008d4,%rdi
0x0000000000400518 +72: movabs $0x6008cc,%rsi
0x0000000000400522 +82: movabs $0x600930,%rdx
0x000000000040052c +92: movabs $0x400658,%rcx
0x0000000000400536 +102: movabs $0x4004d0,%r8
0x0000000000400540 +112: movabs $0x0,%rax
0x000000000040054a +122: callq 0x4003b8 printf@plt
0x000000000040054f +127: pop %rbx
0x0000000000400550 +128: mov %rbp,%rsp
0x0000000000400553 +131: pop %rbp
0x0000000000400554 +132: movabs $0x0,%rax
0x000000000040055e +142: retq
0x000000000040055f +143: nop
End of assembler dump.
(gdb) x/60x main
0x4004d0 main: 0xe5894855 0xd4bf4853 0x00006008 0x48000000
...
A debugging session is active.
Inferior 1 [process 23721] will be killed.
Quit anyway? (y or n)
Options that may allow you to debug
Typical assembly language programming, may just use registers,
or may keep most variables just in registers.
Storing variables in memory may be needed for debugging.
This example starts with a small C program,fib.c
then codes efficient assembly language,fib_64l.asm
Output, shows overflow fib_64l.out
then keeps variables in memory,fib_64m.asm
// fib.c same as computation as fib_64.asm
#include <stdio.h>
int main(int argc, char *argv[])
{
long int c = 95; // loop counter
long int a = 1; // current number, becomes next
long int b = 2; // next number, becomes sum a+b
long int d; // temp
printf("fibinachi numbers\n");
for(c=c; c!=0; c--)
{
printf("%21ld\n",a);
d = a;
a = b;
b = d+b;
}
}
implement fib.c using registers
; fib_64l.asm using 64 bit registers to implement fib.c
global main
extern printf
section .data
format: db '%15ld', 10, 0
title: db 'fibinachi numbers', 10, 0
section .text
main:
push rbp ; set up stack
mov rdi, title ; arg 1 is a pointer
mov rax, 0 ; no vector registers in use
call printf
mov rcx, 95 ; rcx will countdown from 95 to 0
mov rax, 1 ; rax will hold the current number
mov rbx, 2 ; rbx will hold the next number
print:
; We need to call printf, but we are using rax, rbx, and rcx.
; printf may destroy rax and rcx so we will save these before
; the call and restore them afterwards.
push rax ; 32-bit stack operands are not encodable
push rcx ; in 64-bit mode, so we use the "r" names
mov rdi, format ; arg 1 is a pointer
mov rsi, rax ; arg 2 is the current number
mov rax, 0 ; no vector registers in use
call printf
pop rcx
pop rax
mov rdx, rax ; save the current number
mov rax, rbx ; next number is now current
add rbx, rdx ; get the new next number
dec rcx ; count down
jnz print ; if not done counting, do some more
pop rbp ; restore stack
mov rax, 0 ; normal exit
ret
implement fib.c using memory
; fib_64m.asm using 64 bit memory more like C code
; // fib.c same as computation as fib_64m.asm
; #include <stdio.h>
; int main(int argc, char *argv[])
; {
; long int c = 95; // loop counter
; long int a = 1; // current number, becomes next
; long int b = 2; // next number, becomes sum a+b
; long int d; // temp
; printf("fibinachi numbers\n");
; for(c=c; c!=0; c--)
; {
; printf("%21ld\n",a);
; d = a;
; a = b;
; b = d+b;
; }
; }
global main
extern printf
section .bss
d: resq 1 ; temp unused, kept in register rdx
section .data
c: dq 95 ; loop counter
a: dq 1 ; current number, becomes next
b: dq 2 ; next number, becomes sum a+b
format: db '%15ld', 10, 0
title: db 'fibinachi numbers', 10, 0
section .text
main:
push rbp ; set up stack
mov rdi, title ; arg 1 is a pointer
mov rax, 0 ; no vector registers in use
call printf
print:
; We need to call printf, but we are using rax, rbx, and rcx.
mov rdi, format ; arg 1 is a pointer
mov rsi,[a] ; arg 2 is the current number
mov rax, 0 ; no vector registers in use
call printf
mov rdx,[a] ; save the current number, in register
mov rbx,[b] ;
mov [a],rbx ; next number is now current, in ram
add rbx, rdx ; get the new next number
mov [b],rbx ; store in ram
mov rcx,[c] ; get loop count
dec rcx ; count down
mov [c],rcx ; save in ram
jnz print ; if not done counting, do some more
pop rbp ; restore stack
mov rax, 0 ; normal exit
ret ; return to operating system
fib_64.out
fibinachi numbers
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
<- previous index next ->