String Formatting in Assembly Language

section .data
    struct_fmt db "struct1: {%d %d}", 10, 0
    struct_fmt2 db "struct2: {x:%d y:%d}", 10, 0
    type_fmt db "type: point", 10, 0
    bool_fmt db "bool: %s", 10, 0
    int_fmt db "int: %d", 10, 0
    bin_fmt db "bin: %b", 10, 0
    char_fmt db "char: %c", 10, 0
    hex_fmt db "hex: %x", 10, 0
    float_fmt db "float1: %f", 10, 0
    float_fmt2 db "float2: %e", 10, 0
    float_fmt3 db "float3: %E", 10, 0
    str_fmt db "str1: %s", 10, 0
    str_fmt2 db 'str2: "%s"', 10, 0
    str_fmt3 db "str3: ", 0
    pointer_fmt db "pointer: %p", 10, 0
    width_fmt db "width1: |%6d|%6d|", 10, 0
    width_fmt2 db "width2: |%6.2f|%6.2f|", 10, 0
    width_fmt3 db "width3: |%-6.2f|%-6.2f|", 10, 0
    width_fmt4 db "width4: |%6s|%6s|", 10, 0
    width_fmt5 db "width5: |%-6s|%-6s|", 10, 0
    sprintf_fmt db "sprintf: a %s", 10, 0
    io_fmt db "io: an %s", 10, 0

    true_str db "true", 0
    string_val db '"string"', 0
    hex_str db "hex this", 0
    foo_str db "foo", 0
    b_str db "b", 0
    error_str db "error", 0

section .bss
    buffer resb 100

section .text
    global _start

_start:
    ; struct1: {1 2}
    push 2
    push 1
    push struct_fmt
    call printf
    add esp, 12

    ; struct2: {x:1 y:2}
    push 2
    push 1
    push struct_fmt2
    call printf
    add esp, 12

    ; type: point
    push type_fmt
    call printf
    add esp, 4

    ; bool: true
    push true_str
    push bool_fmt
    call printf
    add esp, 8

    ; int: 123
    push 123
    push int_fmt
    call printf
    add esp, 8

    ; bin: 1110
    push 14
    push bin_fmt
    call printf
    add esp, 8

    ; char: !
    push 33
    push char_fmt
    call printf
    add esp, 8

    ; hex: 1c8
    push 456
    push hex_fmt
    call printf
    add esp, 8

    ; float1: 78.900000
    push dword 0x429dc000  ; 78.9 in IEEE 754 format
    push float_fmt
    call printf
    add esp, 8

    ; float2: 1.234000e+08
    push dword 0x4ceb79a3  ; 123400000.0 in IEEE 754 format
    push float_fmt2
    call printf
    add esp, 8

    ; float3: 1.234000E+08
    push dword 0x4ceb79a3  ; 123400000.0 in IEEE 754 format
    push float_fmt3
    call printf
    add esp, 8

    ; str1: "string"
    push string_val
    push str_fmt
    call printf
    add esp, 8

    ; str2: "\"string\""
    push string_val
    push str_fmt2
    call printf
    add esp, 8

    ; str3: 6865782074686973
    push str_fmt3
    call printf
    add esp, 4
    
    mov esi, hex_str
    mov ecx, 8
print_hex:
    xor eax, eax
    lodsb
    push ecx
    push eax
    push hex_fmt
    call printf
    add esp, 8
    pop ecx
    loop print_hex
    
    push 10
    call putchar
    add esp, 4

    ; pointer: (memory address)
    push esp
    push pointer_fmt
    call printf
    add esp, 8

    ; width1: |    12|   345|
    push 345
    push 12
    push width_fmt
    call printf
    add esp, 12

    ; width2: |  1.20|  3.45|
    push dword 0x40599999  ; 3.45 in IEEE 754 format
    push dword 0x3f99999a  ; 1.2 in IEEE 754 format
    push width_fmt2
    call printf
    add esp, 12

    ; width3: |1.20  |3.45  |
    push dword 0x40599999  ; 3.45 in IEEE 754 format
    push dword 0x3f99999a  ; 1.2 in IEEE 754 format
    push width_fmt3
    call printf
    add esp, 12

    ; width4: |   foo|     b|
    push b_str
    push foo_str
    push width_fmt4
    call printf
    add esp, 12

    ; width5: |foo   |b     |
    push b_str
    push foo_str
    push width_fmt5
    call printf
    add esp, 12

    ; sprintf: a string
    push string_val
    push sprintf_fmt
    push buffer
    call sprintf
    add esp, 12
    
    push buffer
    call printf
    add esp, 4

    ; io: an error
    push error_str
    push io_fmt
    call printf
    add esp, 8

    ; Exit the program
    mov eax, 1
    xor ebx, ebx
    int 0x80

This Assembly Language code demonstrates various string formatting techniques. It uses the C standard library functions like printf and sprintf for formatting and printing. Here’s a breakdown of the key points:

  1. We define various format strings and data in the .data section.
  2. The .bss section is used for uninitialized data, like our buffer for sprintf.
  3. In the .text section, we implement the main logic:
    • We use push to pass arguments to functions in reverse order.
    • We call printf for most formatting operations.
    • For floating-point numbers, we use their IEEE 754 representations.
    • We demonstrate width and precision formatting for integers, floats, and strings.
    • We show left-justification using the - flag in the format specifier.
    • We use sprintf to format a string into a buffer.

Note that Assembly Language doesn’t have built-in high-level formatting functions like Go’s fmt package. We rely on C library functions for most formatting operations. The hex string printing is done manually as an example of low-level string manipulation in Assembly.

To run this program, you would need to assemble it with NASM, link it with the C standard library, and then execute the resulting binary. The exact commands may vary depending on your system and assembler.