3 ms·
Curious. These other programmers probably learned the habit from some even older code. Jumping over data isn't a very obvious way of organising code, so probabl
by owl57 4y ago
Curious. These other programmers probably learned the habit from some even older code. Jumping over data isn't a very obvious way of organising code, so probably it served some purpose many years ago.
Maybe someone here knows what was that purpose?
- deleted 4y ago[deleted]
- userbinator 4y agoI remember seeing that in old Asm books too. My best guess is that it avoids having too many forward references, which would take up precious memory in the systems of the time and perhaps reach the limit of the assembler sooner.
- _the_inflator 4y agoMaybe also better for linking the files. At least this was the reason I did it on Amiga when using absolute addresses. I only had to remember the start of the address area even when recompiling.
- bombcar 4y agoThis and the hard coding address comments are the key - forward looking references were expensive (and early enough, impossible) whereas you already knew where your data points were as they came before.
- jstanley 4y agoI wrote a compiler for a small machine that did this so that it could output the string content straight away without having to buffer it in memory.
- jmole 4y agoyou can hard-code values if you know their address in memory. If the data section comes first, then it doesn't move around if your code size changes.
- lboc 4y agoI've seen it done fairly often in mainframe assembler - embed an 'eyecatcher' string near the top of your program and jump to the real entry point. Used as an aid for debugging when reading dumps I believe. Not generally program data though, ususally metadata like program name, author, date assembled etc.
- kragen 4y agoA friend of mine used to program the PDP-8 a lot. The PDP-8 didn't have a stack; to call a subroutine, the JMS FOO instruction would store the return address at (the effective address computed from) FOO, then continue execution at the following word. So to return, the called subroutine would do an indirect jump using the address stored in the memory word before the beginning of its code. I was surprised when he told me how people normally passed arguments. They would put them after the JMS instruction in the caller. So, the callee would indirect from the "return address" stored in FOO to retrieve its arguments, incrementing the return address after each one. So the code to call FOO with arguments 1 and 2 would be (in Intel syntax) JMS FOO DW 1 DW 2 [code to run after returning] Mark Smotherman explains this in more detail, using PDP-8-compatible syntax, in https://people.computing.clemson.edu/~mark/subroutines/pdp8.html https://people.computing.clemson.edu/~mark/subroutines/pdp8..... It seems sort of intuitive to do things this way; if you're writing atan2(3, 4), it's nice to be able to translate this to jms atan2 3 4 rather than, say, mov $3, %rdi; mov $4, %rsi; call atan2. Maybe someone had this habit in their assembly and adapted it to the 8086's calling convention by inserting MOVs and a JMP instruction? You can also imagine that a compiler might be somewhat simpler if it generated code in the order in which it encountered the expressions. Gas lets you switch back and forth between .text and .data, so that if your compiler does this, you still don't have to insert JMP instructions. However, a few years ago when I wrote Ur-Scheme, I did do this for lambda expressions: the code for the lambda expression is generated inline in the middle of its containing code, which then has to contain a jump past it.
- ale42 4y agoOne case where it has a use is on partition (or floppy disk) boot sectors. First instruction is a jump to skip the disk metadata (actually a BIOS parameter block), which is in a fixed place. See https://en.wikipedia.org/wiki/Volume_boot_record https://en.wikipedia.org/wiki/Volume_boot_record