Storing data in segments with assembly
I am learning x86 assembly language, and I understand the purpose and usage of segments. Segments hold vital data, and can also be used to store extra data (ie. Memory Segmentation Model). Here is my question though. If segments can be used to store extra data, how can I make sure that my storing data in them won't overwrite any existing data?
For example, the CS register points to the Code Segment. The Code Segment contains the program's code. If I used the CS register with an offset to 开发者_如何学编程store some data, how would I know where to put my data so as not to overwrite the code that it is storing?
Please let me know. I using Intel syntax assembly and assembling with NASM.
Thanks
Segments never store any data. The segment registers are just "base" address pointers which are used to create 20-bit pointers using only 16-bit registers. For example:
MOV DS, 0001
MOV DI, 0013
MOV AL, DS:[DI] ' this reads from address x00023 in memory
MOV DS, 0002
MOV DI, 0003
MOV AL, DS:[DI] ' this too reads from address x00023 in memory
MOV DS, 0000
MOV DI, 0023
MOV AL, DS:[DI] ' this too reads from address x00023 in memory
As for your question how to make sure that you don't overwrite code with data: it's entirely up to you make sure that you know exactly where in memory you store your code and data!
It's assembly, so you are responsible for everything. To keep your code and data separate is just as easy as keeping two numbers separate. Just use each memory location at most once.
In addition to what's been said already, I'd like to add that you wouldn't normally want to store any "data" in the code segment. That's why you have a Data Segment (base pointed to by DS) or even an "extra" data segment (-> ES). Obvisouly, since your basic assumption must be that whatever is in the code segment, will be executed, it would be very unwise to write random data values there.
If you must store data in the code segment, make sure it will never be executed, like below:
..some code here..
jmp AfterDataDeclaration
db 12 ; declare some data here
AfterDataDeclaration:
..some more code here..
[edit:] If you want to access any specific data, you will always need a reference point, which you will usually most conveniently declare by a label. The assembler will let you access this symbolically, without you having to know its actual address.
The one case where you might want to write something to the code segment is if you want to patch machine code there (i.e., self-modifying code).
As they already mentioned, segment register hold only a 16 bit pointer. This pointer is internally multiplied by 16 so that CPU can address 20-bit big address memory space.
1) If you have enough memory than you can choose 64Kb of RAM for stack, 64Kb for data memory and rest for code memory. Let say that SS (stack segment register) is 0x0400 and DS (data segment register) is 0x0800 and CS (code segment register) is 0x1B00. In this case your code can't override any other memory segment. If you need another 64K of data memory than you can simple extend it with use of ES segment and ES prefix.
2) If you don't have enough memory space (compact program) than you must predict the memory boundaries.
3) If your program use external calls with memory pointers than you must check boundaries. For this purpose in x86 mnemonic exist BOUND
instruction.
精彩评论