this post was submitted on 03 Jul 2023
2 points (100.0% liked)

x86 Assembly

2 readers
1 users here now

founded 1 year ago
MODERATORS
 

As far as i know, on windows it's visual studio, in there you have registers, debugging and other stuff. How about linux?

I tried setting up with this: https://medium.com/@muhammadmeeran2003/how-to-set-up-assembly-language-on-visual-studio-code-2021-587a7b01c9a1 and this: https://github.com/newtonsart/vscode-assembly

That github repo is pretty good, but still no console output and can't see x64 registers while debugging.

Any other good alternatives?

top 1 comments
sorted by: hot top controversial new old
[–] [email protected] 1 points 1 year ago* (last edited 1 year ago)

What I use on Linux:

  1. Vim
  2. GNU Make
  3. NASM (nasm.us)

NASM uses Intel assembly syntax. If you want to learn and use AT&T syntax you can use GNU Assembler (as) provided by the bintutils package instead.

How I use it:

Create a project

mkdir hello_world
cd hello_world
touch Makefile hello_world.asm

Write a Makefile

Note the indents below are supposed to be TAB characters, not spaces.

Makefile

all: hello_world

hello_world.o: hello_world.asm
        nasm -o $@ -f elf32 -g $<

hello_world: hello_world.o
        ld -m elf_i386 -g -o $@ $<

.PHONY: clean
clean:
        rm -f hello_world *.o

Write a program

hello_world.asm

; Assemble as a 32-bit program
bits 32

; Constants
SYS_EXIT  equ 1         ; Kernel system call: exit()
SYS_WRITE equ 4         ; Kernel system call: write()
FD_STDOUT equ 1         ; System file descriptor to write to
EXIT_SUCCESS equ 0

; Variable storage
section .data
        msg:            db "hello world from ", 0
        msg_len:        equ $-msg
        linefeed:       db 0xa ; '\n'
        linefeed_len:   equ $-linefeed

; Program storage
section .text
global _start

_start:
        ; Set up stack frame
        push ebp
        mov ebp, esp

        ; Set base pointer to argv[0]
        add ebp, 8

        ; Write "hello world from " message to stdout
        mov eax, SYS_WRITE
        mov ebx, FD_STDOUT
        mov ecx, msg
        mov edx, msg_len
        int 80h

        ; Get length of argv[0]
        push dword [ebp]
        call strlen
        mov edx, eax

        ; Write the program execution path to stdout
        mov eax, SYS_WRITE
        mov ebx, FD_STDOUT
        mov ecx, [ebp]
        ; edx length already set
        int 80h

        ; Write new line character
        mov eax, SYS_WRITE
        mov ebx, FD_STDOUT
        mov ecx, linefeed
        mov edx, linefeed_len
        int 80h

        ; End of stack frame
        pop ebp

        ; End program
        mov eax, SYS_EXIT
        mov ebx, EXIT_SUCCESS
        int 80h

strlen:
        ; Set up stack frame
        push ebp
        mov ebp, esp

        ; Set base pointer to the first argument on the stack
        ; strlen(buffer);
        ;        ^
        add ebp, 8

        ; Save registers we plan to write to
        push ecx
        push esi

        ; Clear string direction flag
        ; (i.e. lodsb will *increment* esi)
        cld

        ; Zero counter
        xor ecx, ecx

        ; Load address of buffer into the "source index" register
        mov esi, [ebp]
        .loop:
                ; Read byte from esi
                ; Store byte in eax
                lodsb

                ; Loop until string NUL terminator
                cmp eax, 0
                je .return
                ; else: Increment counter and continue
                inc ecx
                jmp .loop

        .return:
                ; Return string length in eax
                mov eax, ecx

                ; Restore written registers
                pop esi
                pop ecx

                ; End stack frame
                pop ebp

                ; Pop stack argument
                ; 32-bit word is 4 bytes. We had one argument.
                ret 4 * 1

Compile and run

$ make
nasm -o hello_world.o -f elf32 -g hello_world.asm
ld -m elf_i386 -g -o hello_world hello_world.o
$ ./hello_world 
hello world from ./hello_world

Adding a debug target to the makefile

Want to fire up your debugger immediately and break on the main entrypoint? No problem.

Makefile

gdb: hello_world
    gdb -tui -ex 'b _start' -ex 'run' --args $<

Now you can clean the project, rebuild, and start a debugging session with one command...

$ make clean gdb
rm -f hello_world *.o
nasm -o hello_world.o -f elf32 -g hello_world.asm
ld -m elf_i386 -g -o hello_world hello_world.o
gdb -tui -ex 'b _start' -ex 'run' --args hello_world
# You're debugging the program in GDB now. Poof.
load more comments
view more: next ›