Assembly minimum, middle, max, sum, and integer average of a list of numbers - linux

I need to create a simple x96-64 assembly language program to compute the min, middle value, max, sum and integer average of a list of numbers. When I try to assemble it gives me errors. My code so far:
; -----
; Define constants.
NULL equ 0 ; end of string
TRUE equ 1
FALSE equ 0
EXIT_SUCCESS equ 0 ; successful operation
SYS_exit equ 60 ; call code for terminate
; -----
lst dd 4220, -1116, 1542, 1240, 1677
dd -1635, 2426, 1820, 1246, -333
dd 2315, -215, 2726, 1140, 2565
dd 2871, 1614, 2418, 2513, 1422
dd -119, 1215, -1525, -712, 1441
dd -3622, -731, -1729, 1615, 2724
dd 1217, -224, 1580, 1147, 2324
dd 1425, 1816, 1262, -2718, 1192
dd -1435, 235, 2764, -1615, 1310
dd 1765, 1954, -967, 1515, 1556
dd 1342, 7321, 1556, 2727, 1227
dd -1927, 1382, 1465, 3955, 1435
dd -225, -2419, -2534, -1345, 2467
dd 1615, 1961, 1335, 2856, 2553
dd -1035, 1835, 1464, 1915, -1810
dd 1465, 1554, -267, 1615, 1656
dd 2192, -825, 1925, 2312, 1725
dd -2517, 1498, -670, 1475, 2030
dd 1223, 1883, -1173, 1350, 2415
dd -335, 1125, 1118, 1713, 3020
length dd 100
lstMin dd 0
lstMid dd 0
lstMax dd 0
lstSum dd 0
lstAve dd 0
evenCnt dd 0
evenSum dd 0
evenAve dd 0
tenCnt dd 0
tenSum dd 0
tenAve dd 0
; *****************************************************************
section .text
global _start
_start:
; ----------------------------------------------
mov rcx, 0
mov ecx, dword [length]
mov eax, dword[lst]
mov dword, [lst +lstMin] eax
mov dword, [lst +lstMax] eax
mov rsi, 0
mov dword [lst +lstSum],0
sumLp:
mov eax, dword [lst+rsi]
add dword [lst + lstSum],eax
cmp eax, dword [lst+lstMin]
jge minDone
mov dword[lstMin],eax
minDone:
cmp eax,dword [lstMax]
jle maxDone
mov dword[lstMax],eax
maxDone:
add rsi, 4
dec rcx
cmp rcx, 0
jne sumLp
mov eax, dword [lstSum]
cdq
idiv dword [length]
mov dword[lstAve],eax
; *****************************************************************
; Done, terminate program.
last:
mov eax, SYS_exit ; call call for exit (SYS_exit)
mov ebx, EXIT_SUCCESS ; return code of 0 (no error)
syscall
The errors I get when assembling with YASM are similar to:
myprog.asm:60: error: unexpected `,' after instruction
myprog.asm:61: error: unexpected `,' after instruction
Why am I getting these errors and how can I fix them?

Related

non blocking tcp client assembly

I am trying to create a tcp client for exchange data. The client should send the message first. If the message was correct, and the user has been property authorized, the system replies with the message 'Ask', confirming that the session has been successfully bound.
;; yasm -g dwarf2 -f elf64 -a x86 message.asm -o msg.o
;; ld -o msg msg.o
segment .bss
listen_socket: resq 1
read_fdset: resb 2
segment .data
packet istruc message
at message.length_mes, dw 0x2800
at message.message_id, dw 0x0100
at message.scheme_id, dw 0x0100
at message.version, dw 0x0100
at message.timestamp, dq 0
at message.keeepaliveinterval, dd 0xe8030000
at message.credentials, dq 0
at message.ext, dw 0
iend
pop_sa istruc sockaddr_in
at sockaddr_in.sin_family, dw 2 ; AF_INET
at sockaddr_in.sin_port, dw 0x2823 ; port 9000
at sockaddr_in.sin_addr, dd 0xf4e8d05b ; 91.208.232.244
at sockaddr_in.sin_zero, dd 0, 0
iend
sockaddr_in_len equ $ - pop_sa
timeval: ;struct
tv_sec dq 0
tv_usec dq 0
timeout: ;struct
to_sec dq 0
to_usec dq 5000
buffer times 512 db 0x0
segment .text
global _start
_start:
struc message
.length_mes resw 1
.message_id resw 1
.scheme_id resw 1
.version resw 1
.timestamp resq 1
.keeepaliveinterval resd 1
.credentials resq 2
.ext resw 1
endstruc
struc sockaddr_in
.sin_family resw 1
.sin_port resw 1
.sin_addr resd 1
.sin_zero resb 8
endstruc
mov rsi, timeval ; struct timespec *tp
mov rdi, 0 ; const clockid_t which_clock - CLOCK_REALTIME
mov rax, 228 ; SYS_CLOCK_GETTIME
syscall
mov r8, qword [tv_sec]
mov r9, qword [tv_usec]
imul r8, 1000000000
sub r8, r9
mov qword [packet + message.timestamp], r8
mov rdi, 2 ; AF_INET
mov rsi, 1 ; SOCK_STREAM
mov rdx, 6 ; PROTO_TCP
mov rax, 41 ; SYS_SOCKET
syscall
cmp rax, 0
jl exit
mov [listen_socket], rax
xor rdx, rdx
mov rsi, 3 ;F_GETFL
mov rdi, [listen_socket]
mov rax, 72 ;SYS_FCNTL
syscall ;return 2
mov rdx, rax
or rdx, 2048
mov rsi, 4 ;F_SETFL
mov rdi, [listen_socket]
mov rax, 72 ;SYS_FCNTL
syscall ; return 0
mov rsi, pop_sa ;
mov rdx, sockaddr_in_len ;
mov rdi, [listen_socket]
mov rax, 42 ; SYS_CONNECT
syscall ; return -115
xor r9, r9
xor r8, r8
xor r10, r10
mov rdx, 40
mov rsi, packet
mov rdi, [listen_socket]
mov rax, 44 ; SYS_SENDTO
syscall ; return 40 - length message
rec:
mov r8, timeout
mov r10, 0
mov rdx, 0
bts [read_fdset], rdi
mov rsi, read_fdset
inc rdi
mov rax, 23 ;SYS_SELECT
syscall ; return 1
xor r9, r9
xor r8, r8
xor r10, r10
mov rdx, 512
mov rsi, buffer
mov rdi, [listen_socket]
mov rax, 45 ; SYS_RECVFROM
syscall ; return 0
cmp rax, 0
jne exit
jmp rec
exit:
mov rdi, 0
mov rax, 60 ; SYS_EXIT
syscall
recvfrom return 0. What wrong in code?

Segmentation fault when trying to sort string elements

I'm trying to make a program that takes a string as an input (made up of 0,1, and 2), and checks if the string[i+1] element is greater than string[i]. if it is greater, the program returns 1, if it is not greater, it returns -1. I keep getting a segmentation fault and i have no idea where it could be.
There is more code to the rest of the program but i have confirmed that the rest works and only raises a Seg Fault when "sort" is called.
My code:
sort:
enter 0,0
pusha
mov edx, dword [ebp+8] ;address of string
mov edi, dword [ebp+12] ;first index
mov esi, dword [ebp+16] ;second index
LOOPYDOOPY:
cmp byte [edx+edi], 0 ;check if the character at first index is 0
je RETMINUS
cmp byte [edx+esi], 0 ;if character at second is 0
je RETPLUS
mov al, byte [edx+esi] ;if first element is greater than second element
cmp byte [edx+edi], al
jl RETMINUS
cmp byte [edx+edi], al ;firstt < second
jg RETPLUS
inc edi
inc esi
jmp LOOPYDOOPY
RETPLUS:
popa
mov eax, 1 ;return 1
jmp END
RETMINUS:
popa
mov eax, -1 ;return -1
END:
leave
ret
No, you were confirmed that the sort raises segfault, not that the rest of code works, quite opposite.
Actually the sort itself is OK, I copied it 1:1 from your question and added only the test calling the sort and displaying results (you can verify I didn't modify single character in your "sort:"), and it works:
(To verify go to http://www.tutorialspoint.com/compile_assembly_online.php and paste this source + run it).
section .text
global _start
_start:
lea ebx,[testString]
xor ecx,ecx ; ecx (i) = 0
.loopI:
cmp [ebx+ecx+2],byte 0
je .allCompared ; not "all", should have been ecx+1 above.
lea edx,[ecx+1] ; edx (j) = i+1
.loopJ:
; call sort
push edx ; j
push ecx ; i
push ebx ; string adr (! OP missing the diff betwen adr and content)
call sort
add esp,12
; display result
mov esi,ecx ; copy i/j to esi/edi
mov edi,edx
test eax,eax
js .firstWasSmaller
xchg esi,edi ; swap esi/edi, esi is "smaller" now
.firstWasSmaller:
pushad
call displaySingleString
mov edx,lenLess
mov ecx,msgLess
call displayStr
xchg esi,edi ; swap esi/edi, esi is "smaller" now
call displaySingleString
mov edx,lenNL
mov ecx,msgNL
call displayStr
popad
; continue in loop
inc edx
cmp [ebx+edx],byte 0
jnz .loopJ
inc ecx
jmp .loopI
.allCompared:
mov eax, 1 ;system call number (sys_exit)
int 0x80 ;call kernel
displaySingleString: ; display partial string from testString+esi
mov edx,testLen
sub edx,esi
lea ecx,[testString+esi]
displayStr:
mov ebx, 1 ;file descriptor (stdout)
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
ret
; original poster code follows, as is (intact):
sort:
enter 0,0
pusha
mov edx, dword [ebp+8] ;address of string
mov edi, dword [ebp+12] ;first index
mov esi, dword [ebp+16] ;second index
LOOPYDOOPY:
cmp byte [edx+edi], 0 ;check if the character at first index is 0
je RETMINUS
cmp byte [edx+esi], 0 ;if character at second is 0
je RETPLUS
mov al, byte [edx+esi] ;if first element is greater than second element
cmp byte [edx+edi], al
jl RETMINUS
cmp byte [edx+edi], al ;firstt < second
jg RETPLUS
inc edi
inc esi
jmp LOOPYDOOPY
RETPLUS:
popa
mov eax, 1 ;return 1
jmp END
RETMINUS:
popa
mov eax, -1 ;return -1
END:
leave
ret
; read only test data + formatting strings
section .rodata
testString: db '00100102', 0
testLen equ $ - testString - 1
msgLess db ' < '
lenLess equ $ - msgLess
msgNL db 0x0a
lenNL equ $ - msgNL
Output I get:
sh-4.3$ nasm -f elf *.asm; ld -m elf_i386 -s -o demo *.o
sh-4.3$ demo
00100102 < 0100102
00100102 < 100102
00100102 < 00102
00100102 < 0102
00100102 < 102
00100102 < 02
00100102 < 2
0100102 < 100102
00102 < 0100102
0100102 < 0102
0100102 < 102
0100102 < 02
0100102 < 2
00102 < 100102
0102 < 100102
100102 < 102
02 < 100102
100102 < 2
00102 < 0102
00102 < 102
00102 < 02
00102 < 2
0102 < 102
0102 < 02
0102 < 2
02 < 102
102 < 2
sh-4.3$

int 10h 13h bios string output not working

i am using nasm and this is my code :
org 0x7c00
bits 16
section .data
zeichen dw 'hello2'
section .text
mov ax,0x7c00
mov es,ax
mov bh,0
mov bp,zeichen
mov ah,13h
mov bl,00h
mov al,1
mov cx,6
mov dh,010h
mov dl,01h
int 10h
jmp $
times 510 - ($-$$) hlt
dw 0xaa55
it does put the cursor on the right position but it prints nothing.
i load this file with qemu-system-i386.
The int10 ah=13h is a string output and in register es:bp has to be the address of the string
For future reference, since i have been trying to get this working for a long time now, here is a working version!
org 0x7c00
bits 16
xor ax, ax
mov es, ax
xor bh, bh
mov bp, msg
mov ah, 0x13
mov bl, [foreground]
mov al, 1
mov cx, [msg_length]
mov dh, [msg_y]
mov dl, [msg_x]
int 0x10
hlt
foreground dw 0xa
msg db 'Beep Boop Meow'
msg_length dw $-msg
msg_x dw 5
msg_y dw 2
times 510 - ($-$$) db 0
dw 0xaa55
here is a version closest to original.
org 0x7c00
bits 16
; video page number.
mov bh, 0
; ES:BP is the pointer to string.
mov ax, 0x0
mov es, ax
mov bp, msg
; attribute(7 is light gray).
mov bl, 0x7
; write mode: character only, cursor moved.
mov al, 1
; string length, hardcoded.
mov cx, 6
; y coordinate
mov dh, 16
; x coordinate
mov dl, 1
; int 10, 13
mov ah, 0x13
int 0x10
; keep jumping until shutdown.
jmp $
msg dw 'hello2'
times 510 - ($-$$) db 0
dw 0xaa55

Raising BRK in assembly on i386 Linux

I found and studied x86 memory access segmentation fault and it won't work in my code. The difference perhaps being that I don't use separate .text and .data segments but keep all in a single segment by creating a custom ELF header. Does that explain why the SYS_BRK call fails?
The program then continues by making the memory pages read/write/execute etc.
I tried to find the minimum code sample that illustrated the issue.
In kdbg the sample does work, but not when started from the command line, hence the message printing.
cpu 386
bits 32
; System calls used
%assign SYS_EXIT 1
%assign SYS_WRITE 4
%assign SYS_BRK 45
%assign SYS_MPROTECT 125
; flags for SYS_MPROTECT
%assign PROT_READ 1
%assign PROT_WRITE 2
%assign PROT_EXEC 4
%assign STDOUT 1
memstart: org 0x08048000
ehdr: ; Elf32_Ehdr (see https://en.wikipedia.org/wiki/Executable_and_Linkable_Format)
db 0x7F, "ELF" ; e_ident[EI_MAG0..EI_MAG03]
db 1 ; e_ident[EI_CLASS]
db 1 ; e_ident[EI_DATA]
db 1 ; e_ident[EI_VERSION]
db 0 ; e_ident[EI_OSABI]
db 0 ; e_ident[EI_ABIVERSION]
times 7 db 0 ; e_ident[EI_PAD]
dw 2 ; e_type
dw 3 ; e_machine
dd 1 ; e_version
dd start ; e_entry
dd phdr - $$ ; e_phoff
dd 0 ; e_shoff
dd 0 ; e_flags
dw ehdrsize ; e_ehsize
dw phdrsize ; e_phentsize
dw 1 ; e_phnum
dw 0 ; e_shentsize
dw 0 ; e_shnum
dw 0 ; e_shstrndx
ehdrsize equ $ - ehdr
phdr: ; Elf32_Phdr
dd 1 ; p_type
dd 0 ; p_offset
dd $$ ; p_vaddr
dd $$ ; p_paddr
dd filesize ; p_filesz
dd filesize ; p_memsz
dd 5 ; p_flags
dd 0x1000 ; p_align
phdrsize equ $ - phdr
memsize: dd 16*4096 ; = 16 * 4K pages
memtop: dd 0
start: ;int 3
xor ebx, ebx ; find the amount of allocated memory
mov eax, SYS_BRK
int 0x80 ; eax contains current memtop
sub eax, memstart ; got enough memory?
test eax, [memsize]
ja memgood
mov eax, memstart ; raise memory limit to memstart + memsize
add eax, [memsize]
mov ebx, eax
mov ecx, eax ; save requested memory size in ecx
mov eax, SYS_BRK
int 0x80
cmp eax, ecx
jne brk_error ; raising memory limit failed
memgood: mov edx, (PROT_READ | PROT_WRITE | PROT_EXEC)
mov ecx, [memsize] ; make memory read/write/execute
mov ebx, memstart
mov eax, SYS_MPROTECT
int 0x80
test eax, eax
js bailout
jmp launch ; lets start the party
brk_error: mov edx, brkelen
mov ecx, brke
mov ebx, STDOUT
mov eax, SYS_WRITE
int 0x80
jmp bailout
brke: db 'SYS_BRK failed, bye', 10
brkelen equ $ - brke
bailout: mov eax, SYS_EXIT
xor ebx, ebx
int 0x80
launch: mov edx, succlen
mov ecx, succ
mov ebx, STDOUT
mov eax, SYS_WRITE
int 0x80
jmp bailout
succ: db 'Success with mem config, bye', 10
succlen equ $ - succ
filesize equ $ - $$
You should use cmp here instead of test:
sub eax, memstart ; got enough memory?
test eax, [memsize]
ja memgood
The memory area described by SYS_BRK start a random offset of 0 to 0x02000000 after the executable unless address space layout randomisation is disabled, which I suspect your debugger does. You can use mmap to allocate memory at a specified address (don't set MAP_FIXED unless you want overwrite existing mappings) .
However this whole exercise with brk and mprotect seems rather pointless as apart from the stack upon program start memory is allocated exactly as the ELF header specified, instead you can:
phdr: ; Elf32_Phdr
dd 1 ; p_type
dd 0 ; p_offset
dd $$ ; p_vaddr
dd $$ ; p_paddr
dd filesize ; p_filesz
dd 16*4096 ; p_memsz
dd 7 ; p_flags
dd 0x1000 ; p_align
phdrsize equ $ - phdr

How can I print the sum to the screen in assembly in this code?

How can i write the output to the screen?
SECTION .data
x:
dd 1
dd 5
dd 2
dd 18
sum:
dd 0
SECTION .text
mov eax,4 ; EAX will serve as a counter
mov ebx,0 ; EBX will store the sum
mov ecx, x ; ECX will point to the current
top:
add ebx, [ecx]
add ecx,4 ; move pointer to next element
dec eax ; decrement counter
jnz top ; if counter not 0, then loop again
done:
mov [sum],ebx ; done, store result in "sum"

Resources