Skip to content

Instantly share code, notes, and snippets.

@rbitr
Created January 27, 2024 18:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rbitr/0649972657f5d0d959eeb71a5b3e0206 to your computer and use it in GitHub Desktop.
Save rbitr/0649972657f5d0d959eeb71a5b3e0206 to your computer and use it in GitHub Desktop.
Timing counting in assembly

The following assembly code counter.asm counts to 10^9, using a linux system call to print:

section .data
    count dd 0          ; Define a 32-bit integer for the count

section .text
    global _start

_start:
    mov ecx, 1000000000 ; Set loop count to 10^9

loop_start:
    add dword [count], 1      ; Increment the count
    loop loop_start     ; Decrement ECX and loop if not zero

    ; Preparing to print the count
    mov eax, 4          ; System call number for sys_write
    mov ebx, 1          ; File descriptor 1 is stdout
    mov ecx, count      ; Pointer to the count to print
    mov edx, 4          ; Number of bytes to write
    int 0x80            ; Call kernel

    ; Exit the program
    mov eax, 1          ; System call number for sys_exit
    xor ebx, ebx        ; Exit code 0
    int 0x80            ; Call kernel
$ nasm -f elf64 counter.asm -o counter.o # assemble
$ ld counter.o -o counter # link
$ ./counter | hexdp
0000000 ca00 3b9a                              
0000004

Note that 0x3b9aca00 == 1000000000. The output defaults to unicode symbols as seen below

Timing:

$ time ./counter
ʚ;
real	0m1.167s
user	0m1.167s
sys	0m0.000s

Check with debugger to confirm it's actually counting

$ gdb ./counter
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./counter...
(No debugging symbols found in ./counter)
(gdb) disassemble _start
Dump of assembler code for function _start:
   0x0000000000401000 <+0>:	mov    $0x3b9aca00,%ecx
End of assembler dump.
(gdb) disassemble 0x0000000000401000,+32
Dump of assembler code from 0x401000 to 0x401020:
   0x0000000000401000 <_start+0>:	mov    $0x3b9aca00,%ecx
   0x0000000000401005 <loop_start+0>:	addl   $0x1,0x402000
   0x000000000040100d <loop_start+8>:	loop   0x401005 <loop_start>
   0x000000000040100f <loop_start+10>:	mov    $0x4,%eax
   0x0000000000401014 <loop_start+15>:	mov    $0x1,%ebx
   0x0000000000401019 <loop_start+20>:	mov    $0x402000,%ecx
   0x000000000040101e <loop_start+25>:	mov    $0x4,%edx
End of assembler dump.

We can see the first three lines load 0x3b9aca00 into ecx and then repeatedly loop until the count reaches the value in ecx, i.e. it's actually looping.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment