Skip to content

Instantly share code, notes, and snippets.

@sertraline
Created July 6, 2019 16:28
Show Gist options
  • Save sertraline/58132e63af8a7dc40dec4b80092f4b14 to your computer and use it in GitHub Desktop.
Save sertraline/58132e63af8a7dc40dec4b80092f4b14 to your computer and use it in GitHub Desktop.
NASM: find odd and even characters in the string, save and print them
; NASM i386
; nasm -f elf print_odd_even.asm
; ld -m elf_i386 print_odd_even.o -o print_odd_even
;
; EXAMPLE
; bash# ./print_odd_even
; Enter the string: The quick brown fox jumps over the lazy dog
; Odd:
; Teqikbonfxjmsoe h aydg
; Even:
; h uc rw o up vrtelz o
;
; Your input:
; The quick brown fox jumps over the lazy dog
SECTION .bss ; non-initialized variables
inp: resb 255 ; user input
out_o: resb 255 ; out_odd
out_e: resb 255 ; out_even
SECTION .data
msg db "Enter the string: ", 0h
msg1 db "Odd: ", 0Ah, 0h
msg2 db "Even: ", 0Ah, 0h
msg3 db "Your input: ", 0Ah, 0h
SECTION .text
global _start
_start:
mov eax, msg
call stprint ; print the greeting message
mov edx, 255 ; - take 255 characters from user input
mov ecx, inp ; | ecx accepts address of the variable to store input
mov ebx, 0 ; | ebx, 0 == write to STDIN file
mov eax, 3 ; | eax, 3 == SYS.READ
int 80h ; - kernel interrupt
call findeven ; the function itself
mov eax, msg1 ; print 1st message ("Odd: ")
call stprint
mov ecx, out_o ; - print OUT_O (out_odd) data
mov edx, 254 ; | which contains odd characters
mov ebx, 1 ; | ebx, 1 == write to STDOUT
mov eax, 4 ; | eax, 4 == SYS.WRITE
int 80h ; - edx contains size of the variable
; ^ we know the exact size of the variable (255 characters) so we won't call stprint
; function for out_o and out_e variables, it is unnecessary.
push 0Ah ; -
mov eax, esp ; | print 0Ah
call stprint ; | (newline character, '\n')
add esp, 4 ; -
mov eax, msg2 ; print 2nd message ("Even: ")
call stprint
mov ecx, out_e ; print OUT_E (out_even) data
mov edx, 254 ; same as above.
mov ebx, 1
mov eax, 4
int 80h
push 0Ah ; -
mov eax, esp ; | print 0Ah
call stprint ; | (newline character, '\n')
add esp, 4 ; -
mov eax, msg3 ; print 3rd message ("Your input: ")
call stprint
mov eax, inp
call stprint ; print original string (user input)
mov ebx, 0 ; exit
mov eax, 1
int 80h
findeven:
push eax ; preserve some registers
push esi
push ebx
mov esi, -1 ; initialize counter with -1, since it will be increased immediately.
mov eax, inp ; move user input string to eax
.iterstring:
inc esi ; counter += 1
cmp byte [eax+esi], 0 ; eax contains original line (input)
jz .finish ; if line ends with zero (end of the line) -> finish
test esi, 1 ; else check if counter is odd/even
; 'test, 1' instruction masks off all bits of a value in the register
; except for the least significant bit (the far right bit).
;
; 00000011 equals 3 in binary.
; test 00000011, 1 will give us 00000001.
;
; 00000100 equals 4 in binary.
; test 00000100, 1 will give us 00000000.
;
; Least significant bit is always 0 if it's even number, and always 1 if it's odd number.
;
; The value of comparison (binary AND) is stored in the zero flag register.
; JZ (jump zero) instruction jumps to the pointed address if zero flag register
; contains zero, and does nothing if ZF contains anything else.
jz .itsodd ; if character is odd (zero flag set), jump to .itsodd
; Here we jump to .itsodd if zero flag is set, however zero flag is set by 'test' if the value is EVEN.
; Our counter is EVEN while the character it points to is ODD.
; Hence why we reverse that: computers start counting from 0, but as humans we start counting from 1.
jmp .itseven ; if even, jump to .itseven
.itseven:
push ebx ; preserve ebx on the stack
mov ebx, 0 ; initialize ebx
mov bl, byte [eax+esi] ; move single byte to bl (lower ebx)
mov byte [out_e+esi], bl ; move bl to the corresponding memory location of OUT variable
pop ebx ; restore ebx
jmp .iterstring ; continue loop
; So let's assume we have 'line' as an input string. 'i' and 'e' are even.
; We're taking byte [line+counter]:
; byte [line+0] contains 'l'
; byte [line+1] contains 'i'
; and so on. 'i' is even, so program should move it to [out+counter].
; If we would use [out] without counter we would replace the very first character
; with a new one.
.itsodd:
push ebx ; same as above
mov ebx, 0
mov bl, byte [eax+esi]
mov byte [out_o+esi], bl
pop ebx
jmp .iterstring
.finish:
pop eax
pop esi
pop ebx
ret
stprint:
push edx ; string print function, taken from
push ecx ; asmtutor.com
push ebx
push eax
call stlen
mov edx, eax
pop eax
mov ecx, eax
mov ebx, 1
mov eax, 4
int 80h
pop ebx
pop ecx
pop edx
ret
stlen:
push ebx
mov ebx, eax
nextch:
cmp byte [eax], 0
jz finish
inc eax
jmp nextch
finish:
sub eax, ebx
pop ebx
ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment