Hi guys. I'm finally learning the structures of a template and have some questions. This is an example file: ; segs.asm ; - - - - - - - - - - - - - STACKSEG SEGMENT STACK 'STACK' variable4 dw 4444h dw 100h dup (?) STACKSEG ENDS ; - - - - - - - - - - - - - MORESTUFF SEGMENT PUBLIC 'HOKUM' variable2 dw 2222h MORESTUFF ENDS ; - - - - - - - - - - - - - DATASTUFF SEGMENT PUBLIC 'DATA' variable1 dw 1111h DATASTUFF ENDS ; - - - - - - - - - - - - - CODESTUFF SEGMENT PUBLIC 'CODE' EXTRN print_num:NEAR , get_num:NEAR ASSUME cs:CODESTUFF,ds:DATASTUFF ASSUME es:MORESTUFF,ss:STACKSEG variable3 dw 3333h main proc far start: push ds sub ax,ax push ax mov ax, DATASTUFF mov ds,ax mov ax, MORESTUFF mov es, ax mov cx, variable1 mov variable1, cx ret main endp CODESTUFF ENDS ; - - - - - - - - - - - - END start 1)Someone told me that it's not good to use "main proc far".Why is it so? 2)start: push ds sub ax,ax push ax What's the use of these instructions? Is it for setting up the return, storing DS, which has PSP(program segment prefix), and also storing the value 0, such that "ret" would give CS and IP a value to orderly quit the program? Currently, I'm not putting "main proc far" and "ret" and "main endp" in my program as if i did, i could not compile it using ml.exe.(tried) So, theoretically speaking, since i have left out "ret", storing PSP and 0h in stack would not be relevant. So, there would be a problem with me quitting the program properly? 3)Actually, what's the use of "main proc far"? And to end it, we use "main endp".BUt why is it that wit this set of code, i would not be able to complie? Hmm..Strange for a newbie like me. So, hope u guys can help!
I'd love to help, but my 16bit DOS programing is so rusty. Try asking these questions on news:comp.lang.asm.x86 Many people on there are qualified to quickly and knowlegibly answer.
NEAR: one that is inbound FAR : one that is outbound When you call a near procedure, the CS register stays the same. Only the IP changes. MYSEGMENT ¦----------------- ¦ ¦ 64K ¦ ¦ disease proc far ;reason for far is because ¦ ;the caller is outside of ¦ ;mysegment ¦ ;my code ¦ ret ¦ disease endp ¦-------------- YOURSEGMENT ¦-------------- ¦ ¦ 64K ¦ ; ¦ call disease ; disease is not in yoursegment ¦ ; so, CS is changed to the segment ¦ ; of MYSEGMENT and IP is changed ¦ ; to the first instruction of disease ¦ ; procedure. ¦ ¦ ;----------------------------------- ¦ ; remember about the CS:IP? the cpu ¦ ; is constantly executing instruction ¦ ; that CS:IP points to. ¦ ; ¦ ; when you immediately call disease ¦ ; the loader(dos) will save the CS:IP ¦ ; with two instruction: ¦ ; ¦ ; PUSH CS and ¦ ; PUSH IP so cs:ip won't get lost. ¦ ; ¦ ; (cs:ip will be put onto the PSP. thus ¦ ; push cs and push ip is not a real ¦ ; instruction for 80x86). ¦ ; ¦ ; and once you reach the RET inside of ¦ ; disease procedure, the loader ¦ ; will POP IP and POP CS <--- restore ¦ ; the saved cs:ip and that's where ¦ ; CPU will begin executing. ¦ ; ¦ ; example (assume that yoursegment is ¦ ; code segment): ¦ ; ¦ ; push cs <-+ ¦ ; [---you don't normally see ¦ ; push ip <-+ this, because the loader ¦ ; will take care of that ¦ ; for you. but keep in mind ¦ ; that those two instruction ¦ ; are always there!(not in ¦ ; your code. therefore, it ¦ ; won't take up exe's size. ¦ ; ¦ ; call disease ;cs:ip is now point to mysegment ¦ ; ;and offset (seg:of) and ¦ ; ;cpu will start executing ¦ ; ;instruction from there. ¦ ; ;once it reaches RET - guess ¦ ; ;what? it will POP IP and | ; ;POP CS (restore the saved cs:ip) | ; ;in other word, reseting cs:ip to ¦ ; ;its original value. | ; ; | ; ;note: push always go with pop | ; ¦ ; next code ;<--- cs:ip is there now and ¦ ; ; start executing instruction ¦ ; ; from there. ¦ ; ------------------------------------ ¦ ; RET: it reset CS:IP and go back where ¦ ; it came from. ¦ ¦ ¦ ¦-------------- now, this is where you have to think abit. disease proc far ret ;remember what RET does? it pop ip & pop cs disease endp that code above works fine. but the problem is that once the cpu reaches ret, CS:IP will contain garbage data! why? because there's no PUSH inside disease procedure. take a look at this: disease proc far mov ax, 2000 push ax ;save ax which is 2000. push ax ; some code ret ;restore ip, ip then = 2000. ;because that's what's on the
You can use Main label far with no "endp" or anything like that, or simply Main: ... Yes, pushing ds and zero is to set up an exit by retn. But ever since DOS2, this is a better way to exit: mov ax,4Cxxh ;xx is ERRORLEVEL int 21h There are some quite good books on DOS programming, such as DOS Programmer's Reference by Dettmann and Wyatt, published by Que. 32-bit asm usually does not use the SEGMENT directive, but uses .MODEL instead.
The first 2 bytes of the psp contain the opcode for int 0x20. Upon loading the program, cammand.com sets ds and es to contain the segment for the psp since it maynot be right before the cs. By pushing ds and 0 onto the stack you set up the ret location, or what to do if you have and extra ret in your program. But for this to work, the assembler (or the coder) has to use an intrasegment return. Since an 80x86 doesn't know what a procedure is (it just follows the call) I don't believe in them. This message was edited by eet_1024, on 6/23/2001 3:12:47 AM
OK! Thanx u guys for ur explainations. I'm now better with the structures of template!