flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
grangerx 14 Jan 2010, 09:10
Hi all,
Sorry if this has been placed in a FAQ somewhere, but I have a question regarding using FASM to write 16-bit DOS programs. I'm trying to do a far call within my assembly program, to another location within the same assembly program. Something like the following: call far cs:label_to_call I found someone's post to another forum where he had written a macro to hard-code the instruction format: http://coding.derkeiler.com/Archive/Assembler/comp.lang.asm.x86/2006-04/msg00319.html and that works, but I'm assuming there's a proper way to do it without having to resort to a macro. I searched as much as I could and didn't find anything terribly informative. The main FASM documentation has a nice mention of jmp instructions and talks about the call instructions within that, but doesn't give any examples. Help? Thanks in advance! -GrangerX |
|||
![]() |
|
bitshifter 14 Jan 2010, 20:05
Haha, what the f?
Code: ; A macro which generates a 16-bit far CALL ("push cs, push ip") ; to the specified label 'nazwa' ; ; Autor / Author: Bogdan 'bogdro' Drozdowski macro skacz nazwa* { local __1_adres mov word [cs:__1_adres], nazwa mov word [cs:__1_adres+2], cs push cs db 9ah ; CALL far __1_adres dd 0 } No need to farcall code in the same segment as CS... A DOS COM file only loads one segment of code anyway... Unless you knew where the code resides at this would be useless... EX: Say we are at CS=0x0050 and some code was at CS=0x1000 then we could use DOS386 method or alernatively call 0x1000:myFunc _________________ Coding a 3D game engine with fasm is like trying to eat an elephant, you just have to keep focused and take it one 'byte' at a time. |
|||
![]() |
|
LocoDelAssembly 14 Jan 2010, 20:27
I think that the purpose of that macro was to complicate disassemblers' life. What I don't understand is why "push cs", opcode 9A already does that so the macro is actually doing "push cs, push cs, push ip".
|
|||
![]() |
|
grangerx 14 Jan 2010, 21:56
DOS386 wrote:
Sorry for the initial confusion and lack of detail/context. I probably shouldn't have said "16-bit DOS" but instead "16-bit BIOS", since I'm working with option-rom code that then boots into a DOS environment to test the results of the option-rom. I realize it's a rather odd-looking call. The reason for it is that what my project is trying to do is glue-together a pair of Intel X86 Option-ROMs into a single binary so that they are both executed at boot. I have 128K of ROM space on the device [Intel NIC], so I'm trying to do this by creating a glue-logic dummy option-rom header that calls the first (tiny 4K, patch) option-rom (which I am writing) and the larger (59K?) option-rom (for which I only have a binary dump, so I can't recompile). Since the roms expect to be far-called, I was hoping I could just do the call far cs:label_to_call since it looks less odd than the push, push, retf method. My end goal (hopefully) is to create an overclockers' option-rom that allows various chipset-specific tweaks to be applied to motherboards that have BIOSes that lack the options to change the settings. The Intel NICs have nice option-roms for this, but since I occasionally PXE boot, I didn't want to lose the ability to do that, too. DOS386 wrote:
I have used this method after seeing it. I was just trying to verify if I was doing it the hard way or the easy way. ![]() DOS386 wrote:
Doh! I just realized, that example is only included with the FASM for DOS; Since I was trying to work at Option-ROM development, I was using FASM for Linux and running my tests in a QEMU VM that boots to a virtual DOS floppy for testing the results, so I didn't even realize the included examples were different. At one point I did try FASM for DOS, but as far as I could tell FASM for Linux produced the same output as FASM for DOS, so I had never even thought to look at the DOS version afterwards. ![]() Thanks very much for your help! -GrangerX |
|||
![]() |
|
grangerx 14 Jan 2010, 22:03
LocoDelAssembly wrote: I think that the purpose of that macro was to complicate disassemblers' life. What I don't understand is why "push cs", opcode 9A already does that so the macro is actually doing "push cs, push cs, push ip". I'm not sure what the author's purpose was, but thanks for the note about the double Push CS. I would have never caught that. I appreciate the friendly expertise! -GrangerX PS. FASM is a pretty awesome assembler. Thanks Tomasz and everyone! |
|||
![]() |
|
edfed 14 Jan 2010, 22:29
to do a 16 bits far call, there are two solutions.
imediate far pointer Code: use16 call 0:function indirect far pointer Code: use16 call far[farpointer] ... farpointer dd 0:function i recommend the second solution because it lets you manage far pointers as datas. |
|||
![]() |
|
LocoDelAssembly 14 Jan 2010, 22:37
Quote:
The CS is placeholder for the actual destination code segment or it is really referring to CS register? If the later is the case then just do this: Code: push cs call label_to_call return_point: ; Example label, you don't actually need it. If the destination register is not CS and can't be known at compile time neither then you'll have to replace "PUSH CS" with "PUSH something" where "something" is a register or a memory location that holds the appropriate value. Another method is just having a memory pointer so you can do this: Code: ; For the example I'll just make the call equivalent as above mov word [pointer+2], cs call far [pointer] . . . pointer dd 0:label_to_call ; Thanks edfed, I didn't know this was possible. . . . label_to_call: [edit]Changed the way the pointer is defined.[/edit] |
|||
![]() |
|
Borsuc 14 Jan 2010, 23:22
edfed wrote: i recommend the second solution because it lets you manage far pointers as datas. _________________ Previously known as The_Grey_Beast |
|||
![]() |
|
edfed 14 Jan 2010, 23:26
but it is not éa& problem on any pc to have 1024 far pointers ( it is only 4096 bytes).
everybody have a place to manage 1024 farpointers for memory management just look at the 64KB GDT only to define 8192 descriptors. |
|||
![]() |
|
Borsuc 14 Jan 2010, 23:28
the data isn't what makes it bigger -- that would be put into the immediate constant anyway. what makes it bigger is the address of the data that is referenced in the call. (with immediates there's no address involved).
I'm just saying he doesn't have to use the second if he doesn't intend to do some data indexing, because there's no point in it. BTW I had no idea you could do 'dd seg:offset' in FASM, thanks. |
|||
![]() |
|
edfed 14 Jan 2010, 23:38
Code: use32
df seg:off
this is for Pmode |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.