• 20 Posts
  • 8 Comments
Joined 1 year ago
cake
Cake day: June 5th, 2023

help-circle








  • I haven’t had that happen to me yet, but it sounds annoying as hell. The “undetermined” language shouldn’t exist. That needs be a silent default. The user should be able select their primary language with a drop-down menu. The combo box would still exist but it’d be completely optional.

    In your case it’d be nice if the “Select Language” drop-down was automatically set to the community’s default language. And maybe put a little red icon next to it when your language settings are incompatible.



  • 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.