Hi all,
First post here, I've only just got started with MASM32 so excuse this if this is a real newbie question
Basically I have an .inc file that basically defines one label with two data initialisers (in the .code section because it was the only way to make it work):
.code
room1:
db "room1", 0
db "this is room 1", 0
My intent is to be able to pass the label as pointer to a section of predefined format to give data about a room. My problem seems to be that trying to access the second string there is that it crashes before it gets to it.
This is the code that I am using to try get the description there:
GetRoomDescription proc rptr:DWORD
mov edi, rptr
SkipName:
cmp edi, 0
je SkippedName
inc edi
jmp SkipName
SkippedName:
inc edi
mov eax, edi
ret
GetRoomDescription endp
The idea is that the start of the code goes to the first data and reads to the null terminator, then move the address into eax and return.
It crashes at the very start of the function.
Here is how I am calling it in the main function:
start:
invoke GetLocOfRoom, offset roomToFind
test eax, eax
je SkipPrint
PrintRoom:
push eax
WriteStringRegNL eax
pop eax
push eax
invoke GetRoomDescription, eax
WriteStringRegNL eax
pop eax
The first WriteString prints out the last the room name perfectly fine, if I add a WriteString to the start of the description function it reads as far as "room" but then crashes after that.
I am truly stumped and since I only started using MASM since yesterday, I'm really stuck
Looking at some of your procedure names, this looks like Kip Irvine book code.
Quote from: hutch-- on June 21, 2018, 01:35:35 AM
Looking at some of your procedure names, this looks like Kip Irvine book code.
All my own code, just going with the docs and my own brain power but my brain power appears to have run out lol
Any idea what I am doing wrong?
First, welcome to the forum! :t
Quote from: CaptainPanda
All my own code, just going with the docs and my own brain power but my brain power appears to have run out lol
Any idea what I am doing wrong?
Post your full source so that we can assemble it to see what is happening with it. Plus just in case there are other errors in your code someone can better assist you when the full source is available. :idea:
Quote from: zedd151 on June 21, 2018, 03:58:16 AM
First, welcome to the forum! :t
Quote from: CaptainPanda
All my own code, just going with the docs and my own brain power but my brain power appears to have run out lol
Any idea what I am doing wrong?
Post your full source so that we can assemble it to see what is happening with it. Plus just in case there are other errors in your code someone can better assist you when the full source is available. :idea:
Ah yes, forgot I'm not asking a question for a high level language, oops lol
Compiled with:
ml /c /coff /Zd zork.asm
Link /subsystem:console zork.obj
.\zork.exeHere it is:
zork.asm
.486
.model flat, stdcall
option casemap :none
include rooms.asm
SplitInputToArr PROTO
StripInputStr PROTO
.data
prompt db "> ", 0
lookStr db "look", 0
space db " ", 0
roomToFind db "room1", 0
.data?
input db 80 dup(?)
strippedInput db 80 dup(?)
verb db 16 dup(?)
noun db 64 dup(?)
.code
start:
invoke GetLocOfRoom, offset roomToFind
test eax, eax
je SkipPrint
PrintRoom:
push eax
WriteStringRegNL eax
pop eax
push eax
invoke GetRoomDescription, eax
WriteStringRegNL eax
pop eax
SkipPrint:
;WriteString prompt
;ReadString input, 80
;invoke StripInputStr
;invoke SplitInputToArr
;WriteStringNL verb
;WriteStringNL noun
invoke ExitProcess, 0
; -------------------------------
SplitInputToArr proc
xor eax, eax
xor ebx, ebx
mov ecx, offset strippedInput
mov edi, offset verb
mov esi, offset noun
SplitArrGetVerb:
cmp eax, 15
jz SplitArrGetVerbTransistToNoun
cmp byte ptr [ecx], 32
jz SplitArrGetVerbTransistToNoun
mov edx, [ecx]
mov [edi], edx
inc ecx
inc edi
inc ax
jmp SplitArrGetVerb
SplitArrGetVerbTransistToNoun:
mov al, 0
mov [edi], al
inc ecx
jmp SplitArrGetNoun
SplitArrGetNoun:
test ecx, ecx
jz SplitArrBeforeEnd1
cmp ebx, 63
jz SplitArrBeforeEnd2
mov al, [ecx]
mov [esi], al
inc bx
inc ecx
inc esi
jmp SplitArrGetNoun
SplitArrBeforeEnd1:
mov al, 0
mov [esi], al
jmp SplitArrEnd
SplitArrBeforeEnd2:
mov al, [ecx]
mov [esi], al
jmp SplitArrEnd
SplitArrEnd:
xor eax, eax
ret
SplitInputToArr endp
; -------------------------------
StripInputStr proc
local temp[80]: byte
xor eax, eax
mov ebx, offset strippedInput
mov ecx, offset input
StripUntilFirstLetter:
cmp byte ptr [ecx], 32
je StripUntilFirstLetter1
jmp StripInnerSpaces
StripUntilFirstLetter1:
inc ecx
jmp StripUntilFirstLetter
StripInnerSpaces:
cmp byte ptr [ecx], 0
je StripRightSpace
cmp byte ptr [ecx], 32
je FoundSpace
xor eax, eax
mov edx, [ecx]
mov [ebx], edx
inc ecx
inc ebx
jmp StripInnerSpaces
FoundSpace:
inc eax
cmp eax, 1
jg IgnoreSpace
mov edx, [ecx]
mov [ebx], edx
inc ecx
inc ebx
jmp StripInnerSpaces
IgnoreSpace:
inc ecx
jmp StripInnerSpaces
StripRightSpace:
cmp byte ptr [ebx], 32
je MoveBackSpace
inc ebx
jmp StripEnd
MoveBackSpace:
dec ebx
jmp StripRightSpace
StripEnd:
mov edx, 0
mov [ebx], edx
xor eax, eax
ret
StripInputStr endp
end start
rooms.asm
include rooms.inc
GetLocOfRoom PROTO :DWORD
GetRoomDescription PROTO :DWORD
TestStrings PROTO :DWORD, :DWORD
.data
newline db 13, 10, 0
room1name db "room1", 0
passed db "passed", 0
;failed db "failed", 0
.data?
val db 8 dup(?)
.code
GetLocOfRoom proc r:DWORD
invoke TestStrings, r, offset room1name
test eax, eax
je room1Pass
jmp GetLocFail
room1Pass:
mov eax, room1
jmp GetLocEnd
GetLocFail:
mov eax, 0
jmp GetLocEnd
GetLocEnd:
ret
GetLocOfRoom endp
GetRoomDescription proc rptr:DWORD
mov edi, rptr
SkipName:
cmp edi, 0
je SkippedName
inc edi
jmp SkipName
SkippedName:
mov eax, edi
ret
GetRoomDescription endp
TestStrings proc s1: DWORD, s2: DWORD
mov eax, sizeof s1
mov ebx, sizeof s2
cmp eax, ebx
jne TestStringsFail
mov edi, s1
mov esi, s2
mov ebx, 0
mov ecx, sizeof s1
TestLetter:
cmp ebx, ecx
je TestStringsPass
mov al, [edi + ebx]
cmp al, [esi + ebx]
jne TestStringsFail
inc ebx
jmp TestLetter
TestStringsPass:
xor eax, eax
jmp TestStringsEnd
TestStringsFail:
mov eax, 1
jmp TestStringsEnd
TestStringsEnd:
ret
TestStrings endp
rooms.inc
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
WriteStringReg MACRO reg
invoke StdOut, reg
ENDM
WriteString MACRO s
invoke StdOut, offset s
ENDM
WriteStringRegNL MACRO reg
invoke StdOut, reg
invoke StdOut, offset newline
ENDM
WriteStringNL MACRO s
invoke StdOut, offset s
invoke StdOut, offset newline
ENDM
ReadString MACRO s, len
invoke StdIn, offset s, len
ENDM
.code
room1:
db "room1", 0
db "this is room 1", 0
Yup, it hangs and crashes after displaying 'Room1'.
I didn't look into it with a debugger, but my best guess is that since esi, edi, and ebx are not getting preserved one of those is the culprit.
I am now going to debug it with xdbg to see whats really happening.
eax is zero at this point:
WriteStringRegNL eax
Check carefully what this code is doing:
GetRoomDescription proc rptr:DWORD
mov edi, rptr
SkipName:
cmp edi, 0
je SkippedName
inc edi
jmp SkipName
SkippedName:
mov eax, edi
.if !eax
mov eax, Chr$("ERROR") ; to avoid the crash
.endif
ret
GetRoomDescription endp
Did you mean cmp byte ptr [edi], 0?
Quote from: jj2007 on June 21, 2018, 05:18:07 AM
eax is zero at this point:
WriteStringRegNL eax
jj's right.
something not right here. I see your desperate attempts to keep a value in eax:
PrintRoom:
push eax ;<------- trying to prevent eax getting overwritten? offset of string "room1" now in eax
WriteStringRegNL eax
pop eax ;<------- eax = 00000000 here
push eax ;<------- trying to prevent eax getting overwritten? push eax (zero at this point)
invoke GetRoomDescription, eax
WriteStringRegNL eax
pop eax
study the code a little better. api's generally put a return value in eax. If you need to save that value, store it in a variable, or local variable. Then put it back into eax when needed.
yup. Getting access violation trying to use 00000000 as an address.
from olly:
0040109E |. 50 PUSH EAX ; /Arg1 ---eax contains address of string 'room1' here
0040109F |. E8 D8000000 CALL zork.0040117C
004010A4 |. 68 00304000 PUSH zork.00403000
004010A9 |. E8 CE000000 CALL zork.0040117C
004010AE |. 58 POP EAX ; eax contains 0
004010AF |. 50 PUSH EAX
004010B0 |. 50 PUSH EAX
004010B1 |. E8 87FFFFFF CALL zork.0040103D
No, it's not the stack, it's the inc edi until edi==0.
Quote from: jj2007 on June 21, 2018, 06:20:17 AM
No, it's not the stack, it's the inc edi until edi==0.
OOps you're right just looked at it again in olly. :P
I was watching the stack variable get changed, and didn't look at the program flow. :icon_redface:
At any rate there is probably more than a dozen ways of doing this little piece of code. Seems a little long and drawn out.
But since he's learning, a good exercise none the less.
Quote from: jj2007 on June 21, 2018, 05:18:07 AM
eax is zero at this point:
WriteStringRegNL eax
Check carefully what this code is doing:
GetRoomDescription proc rptr:DWORD
mov edi, rptr
SkipName:
cmp edi, 0
je SkippedName
inc edi
jmp SkipName
SkippedName:
mov eax, edi
.if !eax
mov eax, Chr$("ERROR") ; to avoid the crash
.endif
ret
GetRoomDescription endp
Did you mean cmp byte ptr [edi], 0?
That seemed to fix it. Can I ask what "byte ptr []" actually does? Is it some form of indirection?
Quote from: CaptainPanda on June 21, 2018, 07:06:37 AMCan I ask what "byte ptr []" actually does? Is it some form of indirection?
It compares the
content of the memory pointed to by edi to zero. Your code just checked whether the pointer itself was zero... and that is not really what you wanted 8)
Quote from: jj2007 on June 21, 2018, 07:36:01 AM
Quote from: CaptainPanda on June 21, 2018, 07:06:37 AMCan I ask what "byte ptr []" actually does? Is it some form of indirection?
It compares the content of the memory pointed to by edi to zero. Your code just checked whether the pointer itself was zero... and that is not really what you wanted 8)
Ah right so I was essentially checking the memory address and not the value, that makes sense now, silly me.
Thanks for the help everyone, just learned of OllyDb from this so I feel I'll be better equipped come next problem.