Related
I am trying to use rep movsb to set a string to a variable. The rep movsb throws an access violation because my mov esi, offset ‘Dog’ is not pointing to the correct memory address. I am including the code and the only thing I can think of is that it might have something to do with the segments. I have a paid attention to the segment registers in the debugger, but I am afraid I do know exactly how to work the problem if the problem is in fact segment registers. Other than that I don’t know, I just know that esi is not being set correctly, but am unsure why.
.386
.model flat, stdcall
option casemap :none
include windows.inc
include user32.inc
include kernel32.inc
addElement PROTO: ptr DbRecord
readArray PROTO
stringLength PROTO : ptr dword
.data?
DbRecord struct
Id dd ?
WordOne db 32 dup(?) ; db is define byte, set value of byte
WordTwo db 32 dup(?)
WordThree db 32 dup(?)
Year dd ?
DbRecord ends
array dword 512 dup(?) ; pointer in memory to start of array
; newElementPointer DbRecord <>
hStdOut dd ?
bytesWritten dd ?
.data
arrayCount dd 0
hello db 'Hello World!', 0
.code
main proc
LOCAL DbRecord01:DbRecord
LOCAL DbRecord02:DbRecord
mov [DbRecord01.Id], 1;
; any other way than one character at a time?
;mov byte ptr [DbRecord01.WordOne], 'D'
;mov byte ptr [DbRecord01.WordOne + 1], 'o'
;mov byte ptr [DbRecord01.WordOne + 2], 'g'
;mov byte ptr [DbRecord01.WordOne + 3], 0
lea edi, DbRecord01.WordOne
mov esi, offset 'Dog' ; esi is not set correctly, inspection of memory does not show 'Dog'
mov ecx, 3
rep movsb
mov byte ptr [DbRecord01.WordTwo], 'C'
mov byte ptr [DbRecord01.WordTwo + 1], 'a'
mov byte ptr [DbRecord01.WordTwo + 2], 't'
mov byte ptr [DbRecord01.WordTwo + 3], 0
mov byte ptr [DbRecord01.WordThree], 'E'
mov byte ptr [DbRecord01.WordThree + 1], 'y'
mov byte ptr [DbRecord01.WordThree + 2], 'e'
mov byte ptr [DbRecord01.WordThree + 3], 0
mov [DbRecord01.Year], 2022;
mov [DbRecord02.Id], 2;
; any other way than one character at a time?
mov byte ptr [DbRecord02.WordOne], 'C'
mov byte ptr [DbRecord02.WordOne + 1], 'a'
mov byte ptr [DbRecord02.WordOne + 2], 'r'
mov byte ptr [DbRecord02.WordOne + 3], 0
mov byte ptr [DbRecord02.WordTwo], 'H'
mov byte ptr [DbRecord02.WordTwo + 1], 'o'
mov byte ptr [DbRecord02.WordTwo + 2], 'u'
mov byte ptr [DbRecord02.WordTwo + 3], 's'
mov byte ptr [DbRecord02.WordTwo + 4], 'e'
mov byte ptr [DbRecord02.WordTwo + 5], 0
mov byte ptr [DbRecord02.WordThree], 'W'
mov byte ptr [DbRecord02.WordThree + 1], 'i'
mov byte ptr [DbRecord02.WordThree + 2], 'n'
mov byte ptr [DbRecord02.WordThree + 3], 'd'
mov byte ptr [DbRecord02.WordThree + 4], 'o'
mov byte ptr [DbRecord02.WordThree + 5], 'w'
mov byte ptr [DbRecord02.WordThree + 6], 's'
mov byte ptr [DbRecord02.WordThree + 7], 0
mov [DbRecord02.Year], 2002;
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov [hStdOut], eax
invoke WriteConsole, hStdOut, offset hello, sizeof hello, offset bytesWritten, NULL
invoke addElement, addr DbRecord01
invoke addElement, addr DbRecord02
invoke readArray
invoke ExitProcess, 0
ret
main endp
addElement proc uses edx DbRecordPointer: ptr DbRecord
Local newElementPointer: Dword
invoke VirtualAlloc, NULL, sizeof DbRecord, MEM_COMMIT, PAGE_READWRITE
mov newElementPointer, eax
invoke RtlMoveMemory, eax , DbRecordPointer, sizeof DbRecord
mov edx, arrayCount
mov dword ptr [array +4*edx], eax
inc edx
mov arrayCount, edx
ret
addElement endp
readArray proc uses ebx
xor ebx, ebx
.while ebx < arrayCount
mov eax, [array+4*ebx]
lea eax, [eax+offset DbRecord.WordOne]
invoke stringLength, eax
mov edx, eax
mov eax, [array+4*ebx]
lea eax, [eax+offset DbRecord.WordOne]
invoke WriteConsole, hStdOut, eax, edx, offset bytesWritten, NULL
mov eax, [array+4*ebx]
lea eax, [eax+offset DbRecord.WordTwo]
invoke stringLength, eax
mov edx, eax
mov eax, [array+4*ebx]
lea eax, [eax+offset DbRecord.WordTwo]
invoke WriteConsole, hStdOut, eax, edx, offset bytesWritten, NULL
mov eax, [array+4*ebx]
lea eax, [eax+offset DbRecord.WordThree]
invoke stringLength, eax
mov edx, eax
mov eax, [array+4*ebx]
lea eax, [eax+offset DbRecord.WordThree]
invoke WriteConsole, hStdOut, eax, edx, offset bytesWritten, NULL
inc ebx
.endw
ret
readArray endp
stringLength proc uses ecx stringPtr: ptr dword
; find length of string
mov edi, stringPtr
mov ecx, -1
mov al, 0
repne scasb
not ecx
mov eax, ecx
ret
stringLength endp
end main
I started to learn assembly some days ago and i write my first ever piece of code using user input, string functions, passing arguments by stack or by register etc...
I have some questions. Do you have some advices to make my code faster. For example, in my atoi function, i know that imul is time consuming. Maybe, there are enormous mistakes but as far as i know, many things to improve for sure. So my main question is : are there fatal errors in this first code and my second is : any type to refactoring code with faster instructions
SYS_READ equ 3
SYS_WRITE equ 4
STDIN equ 0
STDOUT equ 1
%macro printm 2
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, %1
mov edx, %2
int 0x80
%endmacro
%macro prolog 0
push ebp,
mov ebp, esp
%endmacro
%macro epilog 0
mov esp, ebp
pop ebp
%endmacro
section .text
global _start
_start:
; first check if our strlen proc works
push dword msgbegin
call strlen
add esp, byte 4
cmp eax, lenbegin
je .suite ; it works, we continue
; exiting prog if the len computed in rax != lenbegin
mov eax, 1
int 0x80
.suite:
; check if strcpy works printing res (msgbegin -> srcdst)
push dword lenbegin
push dword msgbegin
push dword strdst
call strcpy
add esp, byte 12
push dword lenbegin
push dword strdst
call print
add esp, byte 8
; first input
printm msgbinp1, leninp1
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num1
mov edx, 2
int 0x80
printm msgbinp2, leninp2
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num2
mov edx, 2
int 0x80
printm msgbinp3, leninp3
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, bignum
mov edx, 4
int 0x80
mov edx, bignum
call atoi
cmp eax, 123
je .success ; exit if bignum != 123
mov eax, 1
int 0x80
.success:
; need to strip line feed from bignum
printm bignum, 4
printm msgoutp, lenoutp
; now we compute the sum
mov eax, [num1]
sub eax, '0'
mov ebx, [num2]
sub ebx, '0'
add eax, ebx
add eax, '0'
mov [sum], eax
printm msgres, lenres
; we print it
printm sum, 1
; exiting the programm
mov eax, 1
int 0x80
print:
push ebp
mov ebp, esp
mov eax, 4
mov ebx, 1
mov ecx, [ebp + 8]
mov edx, [ebp + 12]
int 0x80
mov esp, ebp
pop ebp
ret
strcpy:
push ebp
mov ebp, esp
mov ecx, [ebp + 16]
mov esi, [ebp + 12]
mov edi, [ebp + 8]
rep movsb
mov esp, ebp
pop ebp
ret
strlen:
push ebp
mov ebp, esp
push edi
push ecx
mov edi, [ebp + 8]
sub ecx, ecx
sub al, al
not ecx
cld
repne scasb
not ecx
lea eax, [ecx] ; keep null term in size
pop ecx
pop edi
mov esp, ebp
pop ebp
ret
atoi:
xor eax, eax ; zero a "result so far"
.top:
movzx ecx, byte [edx] ; get a character
inc edx ; ready for next one
cmp ecx, '0' ; valid?
jb .done
cmp ecx, '9'
ja .done
sub ecx, '0' ; "convert" character to number
imul eax, 10 ; multiply "result so far" by ten
add eax, ecx ; add in current digit
jmp .top ; until done
.done:
ret
section .data
msgbegin db "hello everyone !", 0xa, 0
lenbegin equ $ - msgbegin
msgbinp1 db "Enter a digit : ", 0xa, 0
leninp1 equ $ - msgbinp1
msgbinp2 db "Enter second digit : ", 0xa, 0
leninp2 equ $ - msgbinp2
msgbinp3 db "Enter third digit : ", 0xa, 0
leninp3 equ $ - msgbinp3
msgoutp db "is equal to 123 !", 0xa, 0
lenoutp equ $ - msgoutp
msgres db "sum of x and y is ", 0xa, 0
lenres equ $ - msgres
strdst times lenbegin db 0
segment .bss
sum resb 1
num1 resb 2
num2 resb 2
bignum resd 4
Thanks you. I started reading the doc but i'm not sure that i understood key concepts.
I'm having trouble with valgrind.
I wrote an assembly program that simulates a game as part of an assignment and I only allocated dynamic memory once for a 2d array called drone_stats. I'm not getting any memory leaks since I did free all memory , but I am getting a bunch of other errors. namely:
Use of uninitialised value of size 4
Uninitialised value was created by a stack allocation
and they all come from this file:
global N
global R
global K
global d
global seed
global drone_stats
global resume
global CORS
global CODEP
global SPP
global seed_dword
global numco
global random
global quit
CODEP equ 0
SPP equ 4
section .rodata
format_int: db "%d"
format_float: db "%f"
section .bss
N: resb 4 ; number of drones
R: resb 4 ; number of rounds per elimination
K: resb 4 ; number of steps per print
d: resb 4 ; max distance away from target that allows destruction
seed: resb 4 ; intial seed for random number
drone_stats: resb 4 ; pointer to an array of pointer, each pointing the an array of the following format:
; [activated: boolean, id: int, x_pos: float, y_pos: float, speed: float, angle: float, score: int]
; drone_i_arr: [[drone_stats]+ drone_id(i)]
SPMAIN: resb 4
SPT: resb 4
CURR: resb 4
STKSZ equ 16*1024
STK1: resb STKSZ
STK2: resb STKSZ
STK3: resb STKSZ
STK4: resb STKSZ
section .data
numco: dd 4
PRINTER: dd f_printer
dd STK1+STKSZ
DRONE: dd f_drone
dd STK2+STKSZ
TARGET: dd f_target
dd STK3+STKSZ
SCHEDULER: dd f_scheduler
dd STK4+STKSZ
CORS: dd PRINTER ; id 0
dd DRONE ; id 1
dd TARGET ; id 2
dd SCHEDULER ; id 3
temp_macro: dd 4
; macro to free memory allocated by param
%macro free_array 1
pushad
push %1
call free
add esp, 4
popad
%endmacro
; macro to allocate %1 blocks of %2 bytes each , and return a pointer to allocated memory in eax
%macro allocate 2
pushad
push %2
push %1
call calloc
add esp, 8
mov [temp_macro], eax
popad
mov eax, [temp_macro]
%endmacro
; macro to read an input from the user according to format %2 and store in variable %1
%macro read_formatted 3 ; sscanf(%3, %2, %1)
pushad
push dword %1
push %2
push %3
call sscanf
add esp, 12
popad
%endmacro
; macro to initialize a single co-routine with id %1
%macro init_co 1
pushad
mov ebx, %1
mov ebx, [4*ebx+CORS]
mov eax, [ebx+CODEP]
mov [SPT], esp
mov esp, [ebx+SPP]
push eax ; push into co-routine's stack
pushfd
pushad
mov [ebx+SPP], esp
mov esp, [SPT]
popad
%endmacro
;macro to generate a number in range of 0 - %1 and to store it's value in %2
%macro generate_random 2
push dword %1
call calc_range
add esp, 4
mov dword [%2], eax
%endmacro
;============================================================::CODE::================================================================
section .text
;funcs
global main
extern f_drone
extern f_printer
extern f_target
extern f_scheduler
extern calc_range
extern calloc
extern free
extern sscanf
;vars
extern target_x
extern target_y
;================================::AUXILIARY FUNCTIONS::===================================
resume: ; save state of current co-routine
pushfd
pushad
mov edx, dword [CURR]
mov dword [edx + SPP], esp ; save current ESP
do_resume: ; load ESP for resumed co-routine
mov esp, dword [ebx + SPP]
mov dword [CURR], ebx ; get the current co routine
popad ; restore resumed co-routine state
popfd
ret ; "return" to resumed co-routine
;--------------------------------
; void quit()
; function to execute a syscall exit right after freeing all memory allocated by the program
quit:
push ebp
mov ebp, esp
mov eax, [drone_stats]
mov ecx, dword [N]
.loop:
mov ebx, [eax]
free_array ebx
add eax, 4
loop .loop
mov eax, [drone_stats]
free_array eax
mov eax, 1
mov ebx, 0
int 0x80
mov esp, ebp
pop ebp
;--------------------------------
; void random()
;
random:
push ebp ; function prologue
mov ebp, esp
pushad
mov edx, 16
seed_loop:
mov ebx,0
mov eax,0
mov ecx,0
mov bx, word [seed]
mov cx, 1
and cx, bx ; check if the 16 bit is '1' or '0'
shr bx, 2 ; get the 14 bit
mov ax, 1
and ax, bx ;check the 14 but
xor cx, ax
shr bx, 1 ; get the 13 bit
mov ax,1
and ax, bx ; check the 13 bit
xor cx, ax
shr bx,2 ; get the 11 bit
mov ax,1
and ax, bx ; check 11 bit
xor cx , ax
mov ax , word [seed]
shr ax, 1
shl cx, 15 ; move result to msb
or ax, cx
mov word [seed], ax
dec edx
cmp edx ,0
jne seed_loop
popad
mov esp, ebp ; function epilogue
pop ebp
ret
main:
push ebp ; function prologue
mov ebp, esp
pushad
; get command-line arguments: <N> <R> <K> <d> <seed>
mov ecx , dword [ebp+8] ; ecx = argc
mov ecx, dword [ebp+12] ; ecx points to argv[0] = program name
mov ebx , dword [ecx+4] ; ebx is a pointer to N(num_drones)
read_formatted N, format_int, ebx
mov ebx , dword [ecx+8] ; ebx is a pointer to R(number of rounds before elimination, Round = N steps)
read_formatted R, format_int, ebx
mov ebx , dword [ecx+12] ; ebx is a pointer to K(number of steps before printing the board)
read_formatted K, format_int, ebx
mov ebx , dword [ecx+16] ; ebx is a pointer to d(the maximum distance)
read_formatted d, format_float, ebx
mov ebx , dword [ecx+20] ; ebx is a pointer to seed(LFSR initialization value)
read_formatted seed, format_int, ebx
; initialize all co-routines
mov ecx, [numco]
xor ebx, ebx ; id of current co-routine
.init_cos:
init_co ebx
inc ebx
loop .init_cos
; intialize target
generate_random 100, target_x ; x: random [0~100]
generate_random 100, target_y ; y: random [0~100]
; allocate an array of pointers. each pointer will point to an array of size 7 that holds all the stats of a single drone:
; step1: allocate an array of N (num of drones) pointers
; step2: allocate N arrays of size 7 and have each one pointed to by a corresponding pointer in the first array
allocate dword [N], 4
mov [drone_stats], eax
mov ecx, [N]
mov ebx, [drone_stats]
.loop_create:
allocate 7, 4 ; allocate an array of size 7 to hold the stats of a drone
mov [ebx], eax ; ebx = drone_stats + i*4, that's a pointer to newly allocated memory for each drone
add ebx, 4
loop .loop_create
; initialize drones
mov ecx, dword [N]
mov edx, dword [drone_stats]
xor edi, edi
; initial stats of drone : [mode: on, id: edi, x: random, y: random, speed: random, angle: random, score: 0]
.loop_init:
mov ebx, [edx] ; array of i'th drone
mov dword [ebx], 1 ; mode: ON
add ebx, 4
mov dword [ebx], edi ; id: edi
add ebx, 4
generate_random 100, ebx ; x: random [0~100]
add ebx, 4
generate_random 100, ebx ; y: random [0~100]
add ebx, 4
generate_random 100, ebx ; speed: random [0~100]
add ebx, 4
generate_random 360, ebx ; angle: random [0~360]
add ebx, 4
mov dword [ebx], 0 ; score: 0
add edx, 4 ; next drone
inc edi ; next id
loop .loop_init
;; printing the board before playing
mov ebx, [CORS]
jmp do_resume
startCo:
pushad
mov [SPMAIN], esp
mov ebx, [CORS +12]
jmp do_resume
popad
mov esp, ebp
pop ebp
ret
Can anyone point to the problem? Thanks ahead!
I made function which should return the number of the highest sequence of the same character in a string. So in case of string 'aabbbcaaaabbccc' it should be 4, in case of 'aaaaa' it should be 5. So for 'aaaaa' this function should return 5, actually it returns 2. I am staring on it long time, but I can't see a mistake.
unsigned long najdlhsia(const char *vstup) {
__asm {
mov eax, 0
mov ecx, 0
mov ebx, vstup
cmp [ebx], 0
je k
mov edx, [ebx]
add ebx, 1
inc eax
inc ecx
c: cmp byte ptr[ebx], 0
je p
cmp [ebx], edx
jne a1
inc ecx
add ebx, 1
jmp c
a1: cmp ecx, eax
jng a2
mov eax, ecx
a2: mov ecx, 1
mov edx, [ebx]
add ebx, 1
jmp c
p: cmp ecx, eax
jng k
mov eax, ecx
k:
}
}
int main()
{
printf("%d", najdlhsia("aaaaa"));
return 0;
}
I put the whole question in 3 images from research it seems I need to use CTRL+R but I don't think that's what I need since I could lower the number a bit lower just can't lower it to the proper amount of 0.
I think the problem is I'm not creating the structs properly probably missing something.
ASM Code:
.text:0040E040 ; =============== S U B R O U T I N E =======================================
.text:0040E040
.text:0040E040
.text:0040E040 ; struct_ARENA *__thiscall code(struct_PLAYER *player, const void *buf, unsigned int len, int a4)
.text:0040E040 sub_40E040 proc near
.text:0040E040
.text:0040E040
.text:0040E040 buf = dword ptr 4
.text:0040E040 len = dword ptr 8
.text:0040E040 a4 = dword ptr 0Ch
.text:0040E040
.text:0040E040 push ebx
.text:0040E041 push esi
.text:0040E042 mov esi, ecx
.text:0040E044 mov eax, [esi+1Ch]
.text:0040E047 test eax, eax
.text:0040E049 jz short loc_40E093
.text:0040E04B mov ecx, [eax+0FF0Ch]
.text:0040E051 xor ebx, ebx
.text:0040E053 test ecx, ecx
.text:0040E055 jle short loc_40E093
.text:0040E057 push edi
.text:0040E058 push ebp
.text:0040E059 mov ebp, [esp+10h+a4]
.text:0040E05D mov edi, 0FB20h
.text:0040E062
.text:0040E062 loc_40E062:
.text:0040E062 mov eax, [edi+eax]
.text:0040E065 cmp eax, esi
.text:0040E067 jz short loc_40E082
.text:0040E069 mov ecx, [eax+38h]
.text:0040E06C test ecx, ecx
.text:0040E06E jnz short loc_40E082
.text:0040E070 mov ecx, [esp+10h+len]
.text:0040E074 mov edx, [esp+10h+buf]
.text:0040E078 push ebp ; a4
.text:0040E079 push ecx ; len
.text:0040E07A push edx ; buf
.text:0040E07B mov ecx, eax ; this
.text:0040E07D call SendPlayerReliablePacket
.text:0040E082
.text:0040E082 loc_40E082:
.text:0040E082
.text:0040E082 mov eax, [esi+1Ch]
.text:0040E085 inc ebx
.text:0040E086 add edi, 4
.text:0040E089 cmp ebx, [eax+0FF0Ch]
.text:0040E08F jl short loc_40E062
.text:0040E091 pop ebp
.text:0040E092 pop edi
.text:0040E093
.text:0040E093 loc_40E093:
.text:0040E093
.text:0040E093 pop esi
.text:0040E094 pop ebx
.text:0040E095 retn 0Ch
.text:0040E095 sub_40E040 endp
.text:0040E095 ; ---------------------------------------------------------------------------
.text:0040E098 align 10h
Here is one that looks better only 1 struct instead of 2 but still same problem