0

I am reading the Art Of Assembly, and on page 250 it says:

You can only push the cs register (popping the cs register would create some interesting program flow control problems).

On page 291 it says:

retf: popd cs:ip

As I see it there are two options:
pop cs: ip is allowed, but you shouldn't use it because the ret instruction is shorter.
pop cs:ip isn't allowed, and only the ret instruction can do it.

Also, if call and ret used segmentation in the past, and in modern computers this "hack" isn't used anymore (or used by OS programmers only), does it mean that every CALL we do is a FAR-JUMP?
Do we always push a 32 bit address or NEAR-JUMP still exists?

BBLN
  • 495
  • 6
  • 19
  • _"does it mean that every CALL we do is a FAR-JUMP?"_ IIRC, they're all NEAR in 32-bit protected mode (as they'll all be within your single 4GB "segment"). – Michael Dec 05 '13 at 12:46
  • @Michael: Wrong; the far jump/call instruction still exists in 32-bit protected mode. Some operating systems (or DOS extenders) even used a segmented 32-bit memory model (where pointers where 48 bits long). However most operating systems use a non-segmented memory layout. – Martin Rosenau Dec 05 '13 at 13:19

2 Answers2

1

In the Intel Developer Manual Volume 2 you can see that the opcodes for near jumps still exists. so the answer is, no, not every call/jump needs to be a far call.

A few examples:

EB cb JMP rel8 Jump short, RIP = RIP + 8-bit displacement sign extended to 64-bits
E9 cw JMP rel16 Jump near, relative, displacement relative to next instruction. Not supported in  64-bit mode.
E9 cd JMP rel32 Jump near, relative, RIP = RIP + 32-bit displacement sign extended to 64-bits
...
EA cd JMP ptr16:16 Jump far, absolute, address given in operand
EA cp JMP ptr16:32 Jump far, absolute, address given in operand
FF /5 JMP m16:16 Jump far, absolute indirect, address given in m16:16
FF /5 JMP m16:32 Jump far, absolute indirect, address given in m16:32.
REX.W + FF /5 JMP m16:64 Jump far, absolute indirect, address given in m16:64. Op

Usually which opcode is used is selected by the compiler/assembler based omn the distance. Of course in the assembler you can influence it by specifically requestion a certain distance (which may be needed if you want to patch the code at runtime).

With regards to segement switches, the need for this has been removed in Windows protected mode environments as a flat memory model is used. However this is a decision by the OS and not didacted by the CPU, so it would still be possible.

Devolus
  • 21,661
  • 13
  • 66
  • 113
  • All these instructions are near jump instructions. The original question was about inter-segment jumps ("far jumps") that modify both the CS and the RIP register. – Martin Rosenau Dec 05 '13 at 13:23
  • @MartinRosenau, `Do we always push a 32 bit address or NEAR-JUMP still exists?` so it's imo not just about inter segement calls. – Devolus Dec 05 '13 at 13:27
  • 1
    Hmm. I think the problem is the question itself. The answer should be that a 32-bit near jump is not the same as a far jump. – Martin Rosenau Dec 05 '13 at 13:34
  • 1
    `pop cs` used to work on 8086 but the opcode, 0x0F, is used as a prefix byte these days. One of the few opcodes to ever have been removed. – Frank Kotler Dec 05 '13 at 14:10
  • If I understand correctly: FAR and NEAR jumps still exists. The OS uses far jumps when its loaded, and the user-space programmer doesn't use segmentation at all, he always uses NEAR jumps in his virtual memory space, and the OS provide segmentation and paging? – BBLN Dec 05 '13 at 14:22
  • Yes, that about sums it's up. – Devolus Dec 05 '13 at 14:23
  • One thing I don't really understand, if the OS has the ability to use 2 byte segment with 4 byte offset, why cant we use more than 4 GB RAM? – BBLN Dec 05 '13 at 14:26
  • 1
    You can find a detailed answer here: http://stackoverflow.com/questions/4039325/assembly-segmented-model-32bit-memory-limit Short Answer is, that the segement is not really a segment but a selector and it doesn't add up to 6bytes linear adress space. – Devolus Dec 05 '13 at 14:33
1

The "far jump absolute" instruction still exists in 32 bit mode; it is 7 bytes long (0xEA, 4 bytes offset, 2 bytes segment).

Some operating systems even used a segmented 32-bit memory layout where pointers were 48 bits in size.

However this is rather inefficient because with 32-bit addresses segmentation will not bring any benefit but only makes a program slower and larger due to the segmentation handling. Therefore most operating systems do not use segmentation any more (with the exception of interrupt handlers and the system call entry).

Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38