Assembly Language - Number Processing
In assembly language, handling numbers involves a combination of base conversion, ASCII conversion, and arithmetic operations. This chapter explains in detail how to input and output numbers in various bases within a program.
Number Representation
All numbers are stored in binary inside the computer, but different bases can be used in programs:
| Base | Radix | NASM Notation | Number Range (32-bit) |
|---|---|---|---|
| Binary | 2 | 0b10101010 or 10101010b |
0 and 1 |
| Octal | 8 | 0o52 or 52o |
0-7 |
| Decimal | 10 | 42 |
0-9 |
| Hexadecimal | 16 | 0x2A or 2Ah |
0-9, A-F |
Relationship Between ASCII and Numbers
What is input and output on the screen are ASCII characters, not binary values.
Understanding the conversion between characters and values is the core of number processing in assembly:
| Character | ASCII Value | Corresponding Value |
|---|---|---|
| '0' | 0x30 (48) | 0 |
| '1' | 0x31 (49) | 1 |
| '9' | 0x39 (57) | 9 |
| 'A' | 0x41 (65) | 10 (hexadecimal) |
| 'F' | 0x46 (70) | 15 (hexadecimal) |
| 'a' | 0x61 (97) | 10 (hexadecimal) |
Character to number: value = ASCII code - '0' (i.e., ASCII code - 0x30)
Number to character: ASCII code = value + '0' (i.e., value + 0x30)
Inputting Numbers (String to Value)
What the user inputs is a sequence of characters, which needs to be converted to a binary value before it can be used in calculations:
Example
; File path: string_to_int.asm
; Convert a decimal digit string to an integer value
section .data
input_str db '12345', 0 ; Input string "12345"
input_len dd 5 ; String length
section .bss
result_val resd 1 ; Store converted value
section .text
global _start
_start:
; Conversion algorithm: result = 0
; result = result * 10 + (current character - '0')
mov esi, input_str ; esi points to input string
mov ecx, ; ecx = loop count
mov eax, 0 ; eax = accumulated result
convert_loop:
mov ebx, 10
mul ebx ; eax = eax * 10
; mul ebx: edx:eax = eax * ebx
mov bl, ; Read current character
sub bl, '0' ; Convert to value: character - '0'
movzx ebx, bl ; Zero-extend ebx (bl -> ebx)
add eax, ebx ; eax = eax + current digit value
inc esi ; Move to next character
loop convert_loop
; eax now = 12345
mov , eax ; Save result
mov eax, 1
mov ebx, 0
int 0x80
Algorithm analysis: Using "12345" as an example:
Round 1: result = 0Γ10 + 1 = 1
Round 2: result = 1Γ10 + 2 = 12
Round 3: result = 12Γ10 + 3 = 123
...Finally obtaining 12345.
Outputting Numbers (Value to String)
Converting a binary value to a displayable decimal string:
Example
; File path: int_to_string.asm
; Convert an integer value to a decimal string and output it
section .data
number dd 12345 ; Number to output
newline db 0xA
section .bss
output_buf resb 12 ; Output buffer (max 32-bit integer is 10 digits + sign + null)
section .text
global _start
_start:
mov eax, ; Load number
mov edi, output_buf + 11 ; edi points to end of buffer
mov byte , 0 ; Null terminator (for debugging)
dec edi
mov ebx, 10 ; Divisor = 10
mov ecx, 0 ; Digit counter
convert_digit:
mov edx, 0 ; Clear edx (div requires edx:eax)
div ebx ; eax = eax/10, edx = eax%10
add dl, '0' ; Convert remainder to character
mov , dl ; Store in buffer (from back to front)
dec edi ; Buffer pointer moves forward
inc ecx ; Digit count +1
cmp eax, 0 ; Is quotient 0?
jne convert_digit ; No, continue loop
; Now edi+1 points to first valid digit character
inc edi ; Fix pointer to point to string start
; Calculate valid character length
; output_buf + 11 - edi is the valid length
; Output number
mov eax, 4
mov ebx, 1
mov ecx, edi ; Point to converted string
; Calculate length
mov edx, output_buf + 11
sub edx, edi ; edx = buffer end - string start
int 0x80
; Output newline
mov eax, 4
mov ebx, 1
mov ecx, newline
mov edx, 1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
Running result:
$ nasm -f elf32 int_to_string.asm -o int_to_string.o
$ ld -m elf_i386 int_to_string.o -o int_to_string
$ ./int_to_string
12345
Hexadecimal Input and Output
Handling hexadecimal requires converting both 0-9 and A-F/a-f:
Example
; File path: hex_output.asm
; Output a value in hexadecimal format
section .data
number dd 0x1A2B3C4D ; Value to output
hex_prefix db '0x'
hex_prefix_len equ $ - hex_prefix
newline db 0xA
section .bss
hex_buf resb 10 ; 8 hex digits + prefix + null
section .text
global _start
_start:
; Output prefix "0x"
mov eax, 4
mov ebx, 1
mov ecx, hex_prefix
mov edx, hex_prefix_len
int 0x80
mov eax, ; Value to convert
mov edi, hex_buf + 8 ; End of buffer (8 hex digits)
mov ecx, 8 ; Loop 8 times (32 bits = 8 hex digits)
hex_loop:
mov edx, 0 ; Prepare for division
mov ebx, 16 ; Divide by 16
div ebx ; Now: eax divided by ebx
; Note: div ebx is actually edx:eax / ebx
; Remainder in edx (0-15), quotient in eax
mov ebx, eax ; Save quotient
; Convert remainder to hex character
mov al, dl
cmp al, 10
jl digit_09 ; 0-9
add al, 'A'-10 ; A-F
jmp store_char
digit_09:
add al, '0' ; 0-9
store_char:
dec edi
mov , al
mov eax, ebx ; Restore quotient
loop hex_loop
; Removed loop, using direct decrement instead
; Output hex digits (8 digits)
mov eax, 4
mov ebx, 1
mov ecx, hex_buf
mov edx, 8
int 0x80
; Output newline
mov eax, 4
mov ebx, 1
mov ecx, newline
mov edx, 1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
Complete Example: Simple Addition Calculator
Input two single-digit numbers from the keyboard, calculate their sum, and output the result:
Example
; File path: simple_calc.asm
; Input two single-digit numbers (0-9), calculate sum and output
section .data
prompt1 db 'Enter first number (0-9): '
prompt1_len equ $ - prompt1
prompt2 db 'Enter second number (0-9): '
prompt2_len equ $ - prompt2
result_msg db 'Sum = '
result_msg_len equ $ - result_msg
newline db 0xA
section .bss
num1 resb 2 ; First number input (1 digit + newline)
num2 resb 2 ; Second number input
result_str resb 3 ; Result string (max 2 digits + newline)
section .text
global _start
_start:
; Prompt for first number
mov eax, 4
mov ebx, 1
mov ecx, prompt1
mov edx, prompt1_len
int 0x80
; Read first number
mov eax, 3
mov ebx, 0
mov ecx, num1
mov edx, 2
int 0x80
; Prompt for second number
mov eax, 4
mov ebx, 1
mov ecx, prompt2
mov edx, prompt2_len
int 0x80
; Read second number
mov eax, 3
mov ebx, 0
mov ecx, num2
mov edx, 2
int 0x80
; Calculate sum
mov al, ; Read first number (ASCII character)
sub al, '0' ; Convert to value
mov bl, ; Read second number
sub bl, '0' ; Convert to value
add al, bl ; Calculate sum
; Convert result to string
mov ah, 0 ; Prepare for division
mov bl, 10 ; Divide by 10
div bl ; al = tens digit, ah = ones digit
; Save result
add al, '0' ; Tens digit to character
mov , al ; Store tens digit
add ah, '0' ; Ones digit to character
mov [result_str+1], ah ; Store ones digit
mov byte [result_str+2], 0xA ; Newline
; Output result message
mov eax, 4
mov ebx, 1
mov ecx, result_msg
mov edx, result_msg_len
int 0x80
; Output calculation result (may be 1 or 2 digits)
mov eax, 4
mov ebx, 1
mov ecx, result_str
cmp byte , '0'
je output_one_digit ; If tens digit is '0', only output ones digit
mov edx, 3 ; 2 digits + newline
jmp do_output
output_one_digit:
inc ecx ; Skip tens digit '0'
mov edx, 2 ; 1 digit + newline
do_output:
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
Running result:
$ nasm -f elf32 simple_calc.asm -o simple_calc.o
$ ld -m elf_i386 simple_calc.o -o simple_calc
$ ./simple_calc
Enter first number (0-9): 7
Enter second number (0-9): 8
Sum = 15
Handling number input and output in assembly requires a clear understanding of ASCII encoding and base conversion. Number to string (int to string) and string to number (string to int) are the two most fundamental utility functions. It is recommended to write and save them as templates for direct reuse later.
YouTip