Skip to main content
added 312 characters in body
Source Link
Roland Illig
  • 21.9k
  • 2
  • 36
  • 84

In a high-level language, I would write it as:

def put_nibble(buf: array[byte], n: int):
    buf[0] = '0' + ((n shr 3) bitand 1)
    buf[1] = '0' + ((n shr 2) bitand 1)
    buf[2] = '0' + ((n shr 1) bitand 1)
    buf[3] = '0' + ((n shr 0) bitand 1)

def char_to_nibble(ch: byte) -> int:
    if '0' <= ch <= '9': return ch
    ch = ch bitor 0x20  # convert to lowercase
    if 'a' <= ch <= 'z': return ch - 'a' + 10
    error

def byte_to_binary(b: str):
    buf = byte[8]  # reserve memory on the stack
    hi = char_to_nibble(b[0])
    put_nibble(buf, hi)
    lo = char_to_nibble(b[1])
    put_nibble(but + 4, lo)
    sys_write(1, buf, 8)

This way you avoid comparing each possible digit on its own.

The above code also reduces memory access to the memory on the stack, since it doesn't need any external strings for the bit patterns.

Sure, the put_nibble code looks a bit repetitive, but you can merge all the '0' + … together into a single addition:

add dword [buf], 0x30303030  ; 0x30 == '0'

You could also compute the buffer for a whole nibble in a register and then write it to memory in a single instruction:

; input: al = the nibble to print
; output: ebx = 4 bytes ASCII buffer containing the 4 binary digits
xor ebx, ebx

rcr al, 1
adc ebx, '0'
rol ebx, 8

rcr al, 1
adc ebx, '0'
rol ebx, 8

rcr al, 1
adc ebx, '0'
rol ebx, 8

rcr al, 1
adc ebx, '0'
rol ebx, 8

mov [buf], ebx

Once you have translated the above high-level code into assembler, you probably want to optimize the code a bit. Or just use a compiler to do the heavy work for you. Write your code in C or in Go, assemble it into machine code and look at the result. Some keywords for searching:

  • go tool objdump
  • gcc -S binary.c -O2

By the way, you should not place the string literals for the prompt and the bit patterns in a writeable segment since they are not intended to be overwritten by any part of your program.

In a high-level language, I would write it as:

def put_nibble(buf: array[byte], n: int):
    buf[0] = '0' + ((n shr 3) bitand 1)
    buf[1] = '0' + ((n shr 2) bitand 1)
    buf[2] = '0' + ((n shr 1) bitand 1)
    buf[3] = '0' + ((n shr 0) bitand 1)

def char_to_nibble(ch: byte) -> int:
    if '0' <= ch <= '9': return ch
    ch = ch bitor 0x20  # convert to lowercase
    if 'a' <= ch <= 'z': return ch - 'a' + 10
    error

def byte_to_binary(b: str):
    buf = byte[8]  # reserve memory on the stack
    hi = char_to_nibble(b[0])
    put_nibble(buf, hi)
    lo = char_to_nibble(b[1])
    put_nibble(but + 4, lo)
    sys_write(1, buf, 8)

This way you avoid comparing each possible digit on its own.

The above code also reduces memory access to the memory on the stack, since it doesn't need any external strings for the bit patterns.

Sure, the put_nibble code looks a bit repetitive, but you can merge all the '0' + … together into a single addition:

add dword [buf], 0x30303030  ; 0x30 == '0'

Once you have translated the above high-level code into assembler, you probably want to optimize the code a bit. Or just use a compiler to do the heavy work for you. Write your code in C or in Go, assemble it into machine code and look at the result. Some keywords for searching:

  • go tool objdump
  • gcc -S binary.c -O2

By the way, you should not place the string literals for the prompt and the bit patterns in a writeable segment since they are not intended to be overwritten by any part of your program.

In a high-level language, I would write it as:

def put_nibble(buf: array[byte], n: int):
    buf[0] = '0' + ((n shr 3) bitand 1)
    buf[1] = '0' + ((n shr 2) bitand 1)
    buf[2] = '0' + ((n shr 1) bitand 1)
    buf[3] = '0' + ((n shr 0) bitand 1)

def char_to_nibble(ch: byte) -> int:
    if '0' <= ch <= '9': return ch
    ch = ch bitor 0x20  # convert to lowercase
    if 'a' <= ch <= 'z': return ch - 'a' + 10
    error

def byte_to_binary(b: str):
    buf = byte[8]  # reserve memory on the stack
    hi = char_to_nibble(b[0])
    put_nibble(buf, hi)
    lo = char_to_nibble(b[1])
    put_nibble(but + 4, lo)
    sys_write(1, buf, 8)

This way you avoid comparing each possible digit on its own.

The above code also reduces memory access to the memory on the stack, since it doesn't need any external strings for the bit patterns.

Sure, the put_nibble code looks a bit repetitive, but you can merge all the '0' + … together into a single addition:

add dword [buf], 0x30303030  ; 0x30 == '0'

You could also compute the buffer for a whole nibble in a register and then write it to memory in a single instruction:

; input: al = the nibble to print
; output: ebx = 4 bytes ASCII buffer containing the 4 binary digits
xor ebx, ebx

rcr al, 1
adc ebx, '0'
rol ebx, 8

rcr al, 1
adc ebx, '0'
rol ebx, 8

rcr al, 1
adc ebx, '0'
rol ebx, 8

rcr al, 1
adc ebx, '0'
rol ebx, 8

mov [buf], ebx

Once you have translated the above high-level code into assembler, you probably want to optimize the code a bit. Or just use a compiler to do the heavy work for you. Write your code in C or in Go, assemble it into machine code and look at the result. Some keywords for searching:

  • go tool objdump
  • gcc -S binary.c -O2

By the way, you should not place the string literals for the prompt and the bit patterns in a writeable segment since they are not intended to be overwritten by any part of your program.

added 312 characters in body
Source Link
Roland Illig
  • 21.9k
  • 2
  • 36
  • 84

In a high-level language, I would write it as:

def put_nibble(buf: array[byte], n: int):
    buf[0] = '0' + ((n shr 3) bitand 1)
    buf[1] = '0' + ((n shr 2) bitand 1)
    buf[2] = '0' + ((n shr 1) bitand 1)
    buf[3] = '0' + ((n shr 0) bitand 1)

def char_to_nibble(ch: byte) -> int:
    if '0' <= ch <= '9': return ch
    ch = ch bitor 0x20  # convert to lowercase
    if 'a' <= ch <= 'z': return ch - 'a' + 10
    error

def byte_to_binary(b: str):
    buf = byte[8]  # reserve memory on the stack
    hi = char_to_nibble(b[0])
    put_nibble(buf, hi)
    lo = char_to_nibble(b[1])
    put_nibble(but + 4, lo)
    sys_write(1, buf, 8)

This way you avoid comparing each possible digit on its own.

The above code also reduces memory access to the memory on the stack, since it doesn't need any external strings for the bit patterns.

Sure, the put_nibble code looks a bit repetitive, but you can merge all the '0' + … together into a single addition:

add dword [buf], 0x30303030  ; 0x30 == '0'

Once you have translated the above high-level code into assembler, you probably want to optimize the code a bit. Or just use a compiler to do the heavy work for you. Write your code in C or in Go, assemble it into machine code and look at the result. Some keywords for searching:

  • go tool objdump
  • gcc -S binary.c -O2

By the way, you should not place the string literals for the prompt and the bit patterns in a writeable segment since they are not intended to be overwritten by any part of your program.

In a high-level language, I would write it as:

def put_nibble(buf: array[byte], n: int):
    buf[0] = '0' + ((n shr 3) bitand 1)
    buf[1] = '0' + ((n shr 2) bitand 1)
    buf[2] = '0' + ((n shr 1) bitand 1)
    buf[3] = '0' + ((n shr 0) bitand 1)

def char_to_nibble(ch: byte) -> int:
    if '0' <= ch <= '9': return ch
    ch = ch bitor 0x20  # convert to lowercase
    if 'a' <= ch <= 'z': return ch - 'a' + 10
    error

def byte_to_binary(b: str):
    buf = byte[8]  # reserve memory on the stack
    hi = char_to_nibble(b[0])
    put_nibble(buf, hi)
    lo = char_to_nibble(b[1])
    put_nibble(but + 4, lo)
    sys_write(1, buf, 8)

This way you avoid comparing each possible digit on its own.

Once you have translated the above high-level code into assembler, you probably want to optimize the code a bit. Or just use a compiler to do the heavy work for you. Write your code in C or in Go, assemble it into machine code and look at the result. Some keywords for searching:

  • go tool objdump
  • gcc -S binary.c -O2

In a high-level language, I would write it as:

def put_nibble(buf: array[byte], n: int):
    buf[0] = '0' + ((n shr 3) bitand 1)
    buf[1] = '0' + ((n shr 2) bitand 1)
    buf[2] = '0' + ((n shr 1) bitand 1)
    buf[3] = '0' + ((n shr 0) bitand 1)

def char_to_nibble(ch: byte) -> int:
    if '0' <= ch <= '9': return ch
    ch = ch bitor 0x20  # convert to lowercase
    if 'a' <= ch <= 'z': return ch - 'a' + 10
    error

def byte_to_binary(b: str):
    buf = byte[8]  # reserve memory on the stack
    hi = char_to_nibble(b[0])
    put_nibble(buf, hi)
    lo = char_to_nibble(b[1])
    put_nibble(but + 4, lo)
    sys_write(1, buf, 8)

This way you avoid comparing each possible digit on its own.

The above code also reduces memory access to the memory on the stack, since it doesn't need any external strings for the bit patterns.

Sure, the put_nibble code looks a bit repetitive, but you can merge all the '0' + … together into a single addition:

add dword [buf], 0x30303030  ; 0x30 == '0'

Once you have translated the above high-level code into assembler, you probably want to optimize the code a bit. Or just use a compiler to do the heavy work for you. Write your code in C or in Go, assemble it into machine code and look at the result. Some keywords for searching:

  • go tool objdump
  • gcc -S binary.c -O2

By the way, you should not place the string literals for the prompt and the bit patterns in a writeable segment since they are not intended to be overwritten by any part of your program.

Source Link
Roland Illig
  • 21.9k
  • 2
  • 36
  • 84

In a high-level language, I would write it as:

def put_nibble(buf: array[byte], n: int):
    buf[0] = '0' + ((n shr 3) bitand 1)
    buf[1] = '0' + ((n shr 2) bitand 1)
    buf[2] = '0' + ((n shr 1) bitand 1)
    buf[3] = '0' + ((n shr 0) bitand 1)

def char_to_nibble(ch: byte) -> int:
    if '0' <= ch <= '9': return ch
    ch = ch bitor 0x20  # convert to lowercase
    if 'a' <= ch <= 'z': return ch - 'a' + 10
    error

def byte_to_binary(b: str):
    buf = byte[8]  # reserve memory on the stack
    hi = char_to_nibble(b[0])
    put_nibble(buf, hi)
    lo = char_to_nibble(b[1])
    put_nibble(but + 4, lo)
    sys_write(1, buf, 8)

This way you avoid comparing each possible digit on its own.

Once you have translated the above high-level code into assembler, you probably want to optimize the code a bit. Or just use a compiler to do the heavy work for you. Write your code in C or in Go, assemble it into machine code and look at the result. Some keywords for searching:

  • go tool objdump
  • gcc -S binary.c -O2