Exception when the program is removing characters from the specified text - exception

Task: write a program to remove the central character in all words of odd length in a given text.
I did this (the idea of ​​the algorithm is to find and write the indexes by which the space is located (in the first cycle) and then rewrite the string with missing characters where necessary):
.586
.model flat, C
option casemap: none
include c:\masm32\include\msvcrt.inc
include c:\masm32\include\kernel32.inc
includelib c:\masm32\lib\msvcrt.lib
includelib c:\masm32\lib\kernel32.lib
printf PROTO C, :VARARG
.data
src db 'hello masm32_ wrld lb 7',0
len equ $-src
dest db ' ',len dup(0),0
end_index db len/2 dup(0)
msg2 db ' %d ', 0
count_1 db 0
count_2 db 0
.code
start:
symbol equ ' '
xor ecx,ecx
xor ebx,ebx
lea esi,src
dec ebx
next:
inc ebx
cmp byte ptr [esi],symbol
jnz notfound
inc ecx
mov byte ptr [end_index + ecx], bl
notfound:
inc esi
cmp byte ptr [esi],0
jz exit
jmp next
exit:
lea esi, src
lea edi, dest
mov ebx, 1
xor ecx, ecx
##_next:
.if byte ptr [end_index + ebx] == 0
jmp ##_ret
.endif
mov al, byte ptr [end_index + ebx]
mov ah, byte ptr [end_index + ebx - 1]
sub al, ah
xor ah, ah
push ebx
mov bl, 2
div bl
pop ebx
add al, byte ptr [end_index + ebx - 1]
and eax, 000000ffh
.if al == cl
inc count_1
inc count_2
inc ebx
jmp ##_next
.endif
mov al, byte ptr [esi + count_1]
mov byte ptr [edi + count_2], al
inc count_1
inc count_2
jmp ##_next
##_ret:
invoke printf, offset dest , 0
ret
end start
But at the first pass of the loop I get
An exception was thrown at address 0x00042092 in asm_7_deb.exe: 0xC0000005: Read access violation at address 0x0008A045.
dissassembler:
start:
00042020 xor ecx,ecx
00042022 xor ebx,ebx
00042024 lea esi,[src (045000h)]
0004202A dec ebx
next:
0004202B inc ebx
0004202C cmp byte ptr [esi],20h
0004202F jne _start+18h (042038h)
00042031 inc ecx
00042032 mov byte ptr end_index (045032h)[ecx],bl
notfound:
00042038 inc esi
00042039 cmp byte ptr [esi],0
0004203C je _start+20h (042040h)
0004203E jmp _start+0Bh (04202Bh)
exit:
00042040 lea esi,[src (045000h)]
00042046 lea edi,[dest (045018h)]
0004204C mov ebx,1
00042051 xor ecx,ecx
##_next:
00042053 cmp byte ptr end_index (045032h)[ebx],0
0004205A jne _start+3Eh (04205Eh)
0004205C jmp _start+8Ch (0420ACh)
#C0001:
0004205E mov al,byte ptr end_index (045032h)[ebx]
00042064 mov ah,byte ptr [ebx+45031h]
0004206A sub al,ah
0004206C xor ah,ah
0004206E push ebx
0004206F mov bl,2
00042071 div al,bl
00042073 pop ebx
00042074 add al,byte ptr [ebx+45031h]
0004207A and eax,0FFh
0004207F cmp al,cl
00042081 jne _start+72h (042092h)
00042083 inc byte ptr [count_1 (045045h)]
00042089 inc byte ptr [count_2 (045046h)]
0004208F inc ebx
00042090 jmp _start+33h (042053h)
#C0003:
00042092 mov al,byte ptr count_1 (045045h)[esi] ; <==== probably it happend here
00042098 mov byte ptr count_2 (045046h)[edi],al ; but i do not understand why
0004209E inc byte ptr [count_1 (045045h)]
000420A4 inc byte ptr [count_2 (045046h)]
000420AA jmp _start+33h (042053h)
##_ret:
000420AC push 0
000420AE push offset dest (045018h)
000420B3 call _printf (041005h)
000420B8 add esp,8
000420BB ret

In order to load [esi + count_1] you need to load the value of count_1 into a register first. Otherwise it takes the address of count_1 plus the value of esi, which is not what you want.
Since count_1 is a byte, use:
movzx edx, byte ptr [count_1]
mov al, [esi+edx]

Related

x86: Access writing violation while using the OFFSET operator to address of array

I am getting the Exception thrown at 0x0044369D in Project2.exe: 0xC0000005: Access violation writing location 0x00000099. From my research so far, I am under the impression this has to do with a null pointer or out of range memory being accessed from the line mov [eax], ecx
I used the offset operator in mov eax, OFFSET arrayfib and I thought that should remedy this. I can't seem to figure out what is causing the issue here.
.model flat, stdcall
.stack 4096
INCLUDE Irvine32.inc
ExitProcess PROTO, dwExitCode: DWORD
.data
arrayfib DWORD 35 DUP (99h)
.code
main PROC
mov eax, OFFSET arrayfib ;address of fibonacci number array
mov bx, 30 ;number of Fibonacci numbers to generate
call fibSequence ;call to Fibonacci sequence procedure
mov edx, OFFSET arrayfib ;passes information to call DumpMem
mov ecx, LENGTHOF arrayfib
mov ebx, TYPE arrayfib
call DumpMem
INVOKE ExitProcess, 0
main ENDP
;----------------------------------------------------------------------------------
;fibSequence
;Calculates the fibonacci numbers to the n'th fibonacci number
;Receives: eax = address of the Fibonacci number array
;bx = number of Fibonacci numbers to generate
;ecx = used for Fibonacci calculation (i-2)
;edx = used for Fibonacci calculation (i-1)
;returns: [eax+4i] = each value of fibonacci sequence in array, scaled for doubleword
;---------------------------------------------------------------------------------
fibSequence PROC
mov ecx, 0 ;initialize the registers with Fib(0) and Fib(1)
mov edx, 1
mov [eax], edx ;store first Fibonacci number in the array
;since a Fibonacci number has been generated, decrement the counter
;test for completion, proceed
mov eax, [eax+4]
fibLoop:
sub bx, 1
jz quit ;if bx = 0, jump to exit
add ecx, edx
push ecx ;save fib# for next iteration before it is destroyed
mov [eax], ecx ;stores new fibonacci number in the next address of array
push edx ;save other fib# before it is destroyed
mov ecx, edx
mov edx, [eax]
mov eax, [eax+4] ;increments accounting for doubleword
pop edx
pop ecx
quit:
exit
fibSequence ENDP
END main
Also if there are any other suggestions I would be happy to hear them. I am new to all this and looking to learn as much as possible.

How to fix "Unhandled exception" error in assembly?

I've written a function that determines if a value is prime or not prime. But when I return from the function, it comes up with an error.
The error message is
Unhandled exception at 0x00000001 in Project.exe: 0xC0000005: Access violation executing location 0x00000001.
This function should return eax.
push ebp
mov ebp, esp
mov eax, [ebp+8] ; store input value
mov ecx, [ebp+8] ; store input value in counter
sub esp, 4 ; local variable
sub ecx, 1 ; avoid compare with itself
cmp eax, 3 ; compare with 1, 2, 3
jbe Prime
L1:
cmp ecx, 3 ; when count=3 to stop
je NotP
mov edx, 0 ; clear edx to save remainder
mov [esp-4], eax ; save input value
div ecx ; divide number
cmp edx, 0 ; check remainder
je NotP ; if remainder=0 then not prime
jmp Prime
loop L1
NotP:
mov eax, 0
push eax ; if delete this ilne still come up error
pop ebp
ret
Prime:
mov eax, 1
push eax ; if delete this ilne still come up error
pop ebp
ret
isPrime endp
mov [esp-4], eax ; save input value
If you plan on using the local variable that you reserved room for, then you have to write:
mov [esp], eax ; save input value
or alternatively write:
mov [ebp-4], eax ; save input value
A correct prolog/epilog would be:
push ebp
mov ebp, esp
sub esp, 4 ; local variable
mov eax, [ebp+8] ; store input value
...
NotP:
mov eax, 0
pop ebp ; remove local variable
pop ebp
ret
Prime:
mov eax, 1
pop ebp ; remove local variable
pop ebp
ret
isPrime endp
cmp edx, 0 ; check remainder
je NotP ; if remainder=0 then not prime
jmp Prime
loop L1
Finding the remainder not zero is not enough to conclude that the number is prime! More tests are needed. For now, that loop L1 instruction is never executed.
e.g. To test 15, your first division does 15 / 14 which yields a non-zero remainder but 15 isn't a prime number.
L1:
cmp ecx, 3 ; when count=3 to stop
je NotP
The top of the loop can't be correct either! Consider testing the number 7.
First division is 7 / 6 and has a remainder so the loop has to continue
Second division is 7 / 5 and has a remainder so the loop has to continue
Third division is 7 / 4 and has a remainder so the loop has to continue
You don't try any more divisions and conclude "not prime", yet 7 is definitively a prime number.

InternetOpenA EXCEPTION_ACCESS_VIOLATION

I do call InternetOpenA in assembler
It is failing with EXCEPTION_ACCESS_VIOLATION on this command:
movdqa xmmword ptr [rsp + 0x20], xmm0
source
start:
sub rsp,30h
lea rcx, [userAgent]
mov rdx,INTERNET_OPEN_TYPE_DIRECT
mov r8,0
mov r9,0
mov qword ptr ds:[rsp+20],0
call qword ptr ds:[<&InternetOpenA>] <---------------
i edit 1st post
its entry point
i will add
sub rsp, 8
and its work
start:
sub rsp, 8
sub rsp,30h
lea rcx, [userAgent]
mov rdx,INTERNET_OPEN_TYPE_DIRECT
mov r8,0
mov r9,0
mov qword ptr ds:[rsp+20],0
call qword ptr ds:[<&InternetOpenA>] <---------------
but i dont understand why stack not aligned at start

Access violation writing location 0x0105100b. Assembly

I'm getting this error when running program:
Access violation writing location 0x0105100b
Does anyone know what's wrong with this code? It's breaking at mov [ecx],dl
.686
.model flat
extern _ExitProcess#4: PROC
public _main
.data
.code
data1 db 61H,62H,63H,64H,65H,66H,67H,68H,69H,70H,0H
data2 db 25 dup (?)
_main:
mov eax, OFFSET data1
mov ecx, OFFSET data2
mov edx, 0
mov ebp, ecx
sub ebp, eax ; licznik
mov dl, BYTE PTR [eax]
mov [ecx],dl
koniec:
push 0
call _ExitProcess#4
END

After executing this nasm function main doesn't continue. It exits without errors

I call the function the following way from main:
main:
;memory alocation ect
call encode
The encode function looks like this:
It does a simple RLE algorithm.
encode:
;IN eax - pointer a memoria elejere
;IN ecx - sor hossza
;OUT eax -pointer az eredmeny elejere
;OUt ecx -a kiirt sor hossza
;elso char
Here it reads the first characer
;push eax
push ebp
xor ebp,ebp
push esi
push edi
push eax
xor edi,edi
Here it allocates memory:
;lefoglal memoria eredmenynek
mov ebx,eax
mov eax,ecx
call mem_alloc
;esi legyen eredmeny memoria kezdete
mov esi,eax
mov eax,ebx
;eax ismet a memoria poiter
xor edx,edx
mov dl,[eax]
; push eax
; xor eax,eax
; mov al,dl
; call io_writeint
; call mio_writeln
; pop eax
;lastChar az elso char
mov [lastChar],dl
The main loop the loops to the "vector"
inc ebp
;dec ecx
.goloop:
mov dl,[eax+ebp]
xor ebx,ebx
mov bl,[lastChar]
cmp dl,bl
jne .newChar
xor ebx,ebx
mov bl,[count]
inc bl
mov [count],bl
.backloop:
loop .goloop
.newChar:
mov [esi+edi],bl
inc edi
mov byte[esi+edi],-1
inc edi
mov bl,[count]
mov [esi+edi],bl
inc edi
mov byte[count],0
cmp ecx,0
ja .backloop
.veg:
mov ebx,esi
mov edx,edi
pop edi
pop esi
pop eax
pop ebp
pop eax
mov eax,ebx
mov ecx,edx
ret
It appears that you push four registers onto the stack but pop five off.
When you CALL an address, the instruction pointer is pushed onto the stack, then the processor JMPs to the label/address you specify. When RET is executed, it POPs off the stack and jumps to the address that it popped off. RET expects that the address that CALL pushed onto the stack will be the next word in the stack, but you have already popped this byte off when you popped more registers than you pushed.
You could try taking the very last
push eax
out of your code.