   Stack problem in asm...
  Hi, im rewritting a 16-bits asm program (usint tasm) that i've made not long ago, everything work fine except for this little problem when i try to read some data from a file to the stack, the program just froze... but if i use a normal buffer it work well. I also read 512 bytes from the floppy to the stack using the same method first, and it seem to work, so my guess is that im not writing/reading data to where i should(in the stack), but i don't know why. Here's the most relevent code:.MODEL SMALL ; Small memory model.386    ; Use 386 functions.STACK 4000H ; Stack size of 16,384 bytes.CODE   ; Code segmentEntryPoint:  ; Program entry pointjmp AfterProcDecl ; Jump over those functions...; Functions declarations (code removed)AfterProcDecl:    ; Program start here......; some code...; Check if a floppy is in the floppy driveCall IsFloppyPresent  ;  <- this work well, using 512 bytes from the stack;Call OpenFile ; <- work well, not using the stackCall StartIO  ; <- Here's the problem, using 9216(512*18) bytes from the stackCall CloseFile; <- work well, not using the stack...; some code...; End the programEndProg:MOV AX,4C00HINT 21H; Variables declarationCurrentDisk  db 2 dup(?)NumberOfDisk db 2 dup(?)FileHandle   db 2 dup(?)END EntryPoint[/Source][/source][/source][/source][/source]And here's the function that work:; ==============================================; Try to read the first sector of the floppy; ==============================================IsFloppyPresent: push bp  ; Save bpsub sp, 512   ; Allocate 512 bytes from the stackmov bp, sp    ; Make bp point to the current stack positionCall ClearRegs; Clear the registersmov ax, 0201h ; Read Mode, Read 1 sectormov bx, bp    ; Read data to the stackmov cx, 0001h ; Cylinder #, Sector #xor dx, dx    ; Head #, drive #push es  ; Save espush cs  ; Put cs...pop  es  ; ...Into esint 13h  ; Try to read a sector from the floppycmp al, 0; Error if al = 0pop es   ; Restore esje NoFloppyPresentadd sp, 512    ; Reset the stack pointerpop bpmov ax, 1ret ; Return sucess!NoFloppyPresent:add sp, 512   ; Reset the stack pointerpop bpmov ax, 0ret ; Return failure...[/Source][/source][/source][/source][/source]And the one that don't...StartIO:   ; THIS FUNCTIOM DONT WORK WELLpush bp    ; Save bpsub sp, 9216    ; Allocate 9216 bytes from the stackmov bp, sp ; Setup the stack pointerCall ClearRegs  ; Clear registers ax to dxmov cx, 1  ; init cx  (track 0, 1st sector)xor dx, dx ; clear dx (head 0)ReadNextSector:push dx    ; Save cx and dx on the stack...push cx    ; ... and restore them when writing; ==============================================; Read 9kb from the file; ==============================================mov ax, 3F00h; Read file modemov bx, word ptr CS:[FileHandle] ; The file handlemov cx, 9216 ; Number of bytes to readmov dx, bp   ; Stack buffer addresspush ds ; Save dspush cs ; Put cspop ds  ; Into dsint 21h ; Read the 18 sectors ; <- crashpop ds  ; Restore dsjc ReadFileError  ; Close the file on error...  ; more code removed...[/Source][/source][/source][/source][/source]What i am doing wrong? Am i allocating memory from the stack right? Any help will be greatly apreciated.BTW sp = 4000h before entering those functions, so it has the good value, and using something like:TmpBuffer   db 2400h dup(?)and replacing :mov dx, bp   ; Stack buffer addressby:mov dx, OFFSET TmpBuffer    ; Static buffer work, but i really need to use the stack for this.[Edited by - Vortez on June 7, 2010 12:32:21 PM]
  Its been a long while but....I see a few flaws. Reading a file in without knowing its actual size is never a clean operation. Reading it directly to the stack is even more prone to trouble. If you absolutely must have it on the stack then read it in to a buffer, check it to make sure the data is good and only then copy it to the stack.An even worse problem is putting data on the stack and attempting to use it after the routine returns. This will almost always result in corruption as the same stack space gets reused by the next call and the various interrupts. The only way to do this is to reserve the space in the calling routine and then passing the stack address.and just a minor suggestion:cmp al, 0; Error if al = 0pop es   ; Restore esje NoFloppyPresentthis code might not always jump correctly because you popped es after the compare but before the actual jump test. pop es   ; Restore escmp al, 0; Error if al = 0je NoFloppyPresentwould be better IMHO.A Faster register clear:XOR EAX,EAXXOR EBX,EBXXOR ECX,ECX XOR EDX,EDX;  Humm after debugging for a while i found the problem, i needed to pop ss into dx, the stact segment, not cs or ds, now i can see the data being write at the good location.Quote:Original post by BrianLarsenI see a few flaws. Reading a file in without knowing its actual size is never a clean operation. Reading it directly to the stack is even more prone to trouble. If you absolutely must have it on the stack then read it in to a buffer, check it to make sure the data is good and only then copy it to the stack.The files sizes that the prog will read are know in advance, and wont change so that's not a problem.Quote:Original post by BrianLarsenAn even worse problem is putting data on the stack and attempting to use it after the routine returns. This will almost always result in corruption as the same stack space gets reused by the next call and the various interrupts. The only way to do this is to reserve the space in the calling routine and then passing the stack address.Of course. I dont intend using it this way either.Quote:Original post by BrianLarsencmp al, 0 ; Error if al = 0pop es ; Restore esje NoFloppyPresentthis code might not always jump correctly because you popped es after the compare but before the actual jump test.pop es ; Restore escmp al, 0 ; Error if al = 0je NoFloppyPresentwould be better IMHO.Yea, i knew about that but wasen't sure if it was right, this way is better indeed.Quote:Original post by BrianLarsenA Faster register clear:XOR EAX,EAXXOR EBX,EBXXOR ECX,ECXXOR EDX,EDXhehe that's just what the function ClearRegs does:ClearRegs:xor ax, axxor bx, bxxor cx, cxxor dx, dxretMake my code more compact...   ;  Making a function call to clear four registers is pretty bad.Why are you writing any of this in assembly instead of, say, C?;  Well, it's a bit complicated, im doing this little program so i can create a bootsector for my multi-boot dvd, to perform some task when the user choose this bootsector to load from, so it has to be written in asm, and the code has to fit into 2k bytes, so that's why im pretty limited. I've made the function to minimize code size, since im using it a lot.   ;  Never assume a file will not change size. Always assume malicious intent when dealing with data that is outside of your code.....Clearing registers is not usually needed in ASM unless you explicitly need a zero in them. Calling a routine to XOR 4 registers tends to imply a problem with your design. Also you should check the actual generated code. Unless your calling a local routine by a short jump the XOR's may actually use less space. Op codes vary in size and XOR-ing a register with itself is a very short op-code.Boot sectors sure have gotten big over the years... Use to be, you only had 200 bytes.   