Study guide question: I have no idea what the difference is between writing it in 16bit and 32 bit, though. Can someone clarify how that changes things?
Write an 80×86 assembly program that will add word size signed integers in memory and
stop when it sees a zero. The sum will always be greater than -32768 and less than 32767.
The sum should be written to memory. If only a zero is in the string of integers place a 0
in total. Use the JNZ command. (If the last operation results in a zero jump to a label.)
16bit
integs DW 2,-300, 54, 30, 8,,-240, 0
total DW ?
32bit
integs WORD 2,-300, 54, 30, 8,,-240, 0
total WORD ?
There are several differences in 32-bit code as opposed to 16-bit:
First and foremost, of course, your registers and indexes and data reads are typically 32 bits wide. (You can change this with address-size and operand-size prefixes. Typically you won’t use the address-size prefix, but for 32-bit code reading 16-bit words, i can see the operand-size prefix being used pretty extensively. Some assemblers will take care of that for you.)
The 32-bit registers have names starting with
E, and are basically extensions of the 16-bit registers. (For example,AXis the low word ofEAX. Unfortunately, there’s no built-in way to access the high word. You’ll have to rotate or shift the register to get to the upper 16 bits.)Indexing is different as well. 16-bit code is far more limited in how it can combine registers. You’ll see a lot of
[BX+SI], but IIRC[AX+BX]isn’t even legal. It is in 32-bit code. Plus, 32-bit code can scale the first term (times 1, 2, 4…i forget whether 8 is allowed). For example,[EBX*4+ECX].In 16-bit code, the registers have rather strict purposes; for example, CX is a counter, BX is basically a base pointer, SI and DI are indexes — hence their names. Working against that tends to mean jumping through hoops. In 32-bit code, this is noticeably relaxed; while the registers still mostly retain their special purposes, the more flexible indexing lets just about any free register serve as an index.
Protected mode is pretty much always on. (There’s special cases, but they’re not common anymore. You’d have to be writing a DOS game or something to see it; every decent OS jumps into protected mode as soon as it can.) There’s a bunch of restrictions and such that go along with it. Most will be invisible to you unless you try to do kernel-level stuff, though. Most 16-bit code is intended to run in “real mode” or “virtual 8086” mode, where the CPU basically acts like a really fast 8086, funky addressing and all.
Oh yeah, addressing. 16-bit code uses “segments”, where the segment registers (
CS,DS, etc) are simply shifted left by 4 bits and added to the “offset” to give you a 20-bit value (max: 1MB). 32-bit code is nowhere near that regular, but also nowhere near that limited; it repurposes the segment registers as “selectors”, which can point just about anywhere in the CPU’s address space, but have to be set up in a descriptor table (GDT or LDT). In practice, 32-bit code almost always sets all the segments to point to the same region of memory. That’s called a “flat model”, and is by far the most common setup. 16-bit code has like a half dozen different memory models, depending on how big the code and data need to be.The directives/instructions for raw data are typically the same;
DWstill typically means “this is a word”,DDmeans “this is a dword”, etc.By the way, “x86” and “80×86” typically imply “32-bit” — mostly because the term wasn’t common til 32-bit CPUs came about.