ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º Adam's Assembler Tutorial 1.0 ÇÄ¿ º º ³ º PART VI º ³ ÈÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Contact : blackcat@faroc.com.au http://www.faroc.com.au/~blackcat Note : Adam's Assembler Tutorial is COPYRIGHT, and all rights are reserved by the author. You may freely redistribute only the ORIGINAL archive, and the tutorials should not be edited in any ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Hello again, Assembler coders. This edition is a little late, but I hada lot of other things to finish, and I'm working on a game of my own now.
It's a strategy game, like Warlords II, and I think I'm going to have towrite most of the code for it in 640x480, not my beloved 320x200 - but I may change my mind. Heck, the amount of games I started writing but never gotaround to finishing is pretty large, so this one may not get all that far.
Anyway, I said we'd be having a look at some line/circle routines this week, ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Last week we came up with the following horizontal line routine - mov ax, 0A000h mov es, ax ; Point ES to the VGA sub cx, ax ; CX = Difference of X2 and X1 shl dx, 6 ; Y SHL 6 add dx, bx ; DX = Y SHL 8 + Y SHL 6 mov al, color ; Put the color to plot in AL rep stosb ; Draw the line Now although this routine was much faster than the BGI routines, (or whateveryour compiler provides), it could be improved upon greatly. If we go through the routine with the list of clock ticks provided in the last tutorial, you'll I'll leave optimization up to you for now, (we'll get onto that in a latertutorial), but either replacing the STOSB with MOV ES:[DI], AL or STOSW will speed things up quite a bit. Don't forget that if you decide to use a loop,to whack words onto the VGA, you will have to decrement CX by one.
Now, lets get on to a vertical line. We'll have to calculate the offset of the first pixel as we did with the horizontal line routine, so something likethis should do: mov ax, 0A000h ; Put the VGA segment into AX mov es, ax ; Point ES to the VGA mov ax, Y1 ; Move the first Y value into AX shl ax, 6 ; Y x 2 to the power 6 mov di, ax ; Move the new Y value into DI shl ax, 2 ; Now we have Y = Y x 320 add di, ax ; Add that value onto DI mov cx, Y2 ; Store Y2 in CX mov al, Color ; Store the color to plot with in AL sub cx, Y1 ; CX = vertical length of line Plot: mov es:[di], al ; Put the a pixel at the current offset add di, 320 ; Move down to the next row dec cx ; Decrement CX by one jnz Plot ; If CX <> 0, then keep on plotting Not a fantastic routine, but it's pretty good all the same. Note how it was possible to perform a comparison after DEC CX. This is an extremely usefulconcept, so don't forget that it is possible.
Have a play around with the code, and try and speed it up. Try other methods of finding the offset, or different methods of flow control.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Now, that was the easy stuff. We are now going to have a look at a lineroutine capable of drawing diagonal lines.
The following routine was picked up from SWAG, author unknown, and is an ideal routine to demonstrate a line algorithm. It is in great need ofoptimization, so this can be a task for you - if you wish. Some of the 1) Whoever wrote it had never heard of XCHG - this would save quite a few clock ticks; 2) It makes one of the great sins of unoptimized code - it will say, move a value to AX, and then perform an operation involving AX in the next instruction, thus incurring a penalty cycle. (We'll talk about this next week).
3) It works with BYTES not WORDS, so the speed of writing to the VGA could 4) And the biggest sin of all, it uses a MUL to find the offset. Try using shifts or an exchange to speed things up.
Anyway, I put the comments in, and I feel that it is fairly self explanatory as it is, so I won't go over how it works. You should be able to pick thatup for yourself. Work through the routine, and see how the gradient for the Procedure Line(X1, Y1, X2, Y2 : Word; Color : Byte); Assembler; Asm { Line } mov ax, [X2] { Move X2 into AX } sub ax, [X1] { Get the horiz length of the line - X2 - X1 } jnc @Dont1 { Did X2 - X1 yield a negative result? } neg ax { Yes, so make the horiz length positive } @Dont1: mov [DeX], ax { Now, move the horiz length of line into DeX } mov ax, [Y2] { Move Y2 into AX } sub ax, [Y1] { Subtract Y1 from Y2, giving the vert length } jnc @Dont2 { Was it negative? } neg ax { Yes, so make it positive } mov [DeY], ax { Move the vert length into DeY } cmp ax, [DeX] { Compare the vert length to horiz length } jbe @OtherLine { If vert was <= horiz length then jump } mov ax, [Y1] { Move Y1 into AX } cmp ax, [Y2] { Compare Y1 to Y2 } jbe @DontSwap1 { If Y1 <= Y2 then jump, else. } mov bx, [Y2] { Put Y2 in BX } mov [Y1], bx { Put Y2 in Y1 } mov [Y2], ax { Move Y1 into Y2 } { So after all that. } { Y1 = Y2 and Y2 = Y1 } mov bx, [X2] { Put X2 into BX } mov [X1], bx { Put X2 into X1 } @DontSwap1: mov [IncF], 1 { Put 1 in IncF, ie, plot another pixel } mov ax, [X1] { Put X1 into AX } cmp ax, [X2] { Compare X1 with X2 } jbe @SkipNegate1 { If X1 <= X2 then jump, else. } neg [IncF] { Negate IncF } @SkipNegate1: mov ax, [Y1] { Move Y1 into AX } mov bx, 320 { Move 320 into BX } mul bx { Multiply 320 by Y1 } mov di, ax { Put the result into DI } add di, [X1] { Add X1 to DI, and tada - offset in DI } mov bx, [DeY] { Put DeY in BX } mov cx, bx { Put DeY in CX } mov ax, 0A000h { Put the segment to plot in, in AX } mov es, ax { ES points to the VGA } mov dl, [Color] { Put the color to use in DL } mov si, [DeX] { Point SI to DeX } mov es:[di], dl { Put the color to plot with, DL, at ES:DI } add di, 320 { Add 320 to DI, ie, next line down } sub bx, si { Subtract DeX from BX, DeY } jnc @GoOn1 { Did it yield a negative result? } add bx, [DeY] { Yes, so add DeY to BX } add di, [IncF] { Add the amount to increment by to DI } loop @DrawLoop1 { No negative result, so plot another pixel } jmp @ExitLine { We're all done, so outta here! } mov ax, [X1] { Move X1 into AX } cmp ax, [X2] { Compare X1 to X2 } jbe @DontSwap2 { Was X1 <= X2 ? } mov bx, [X2] { No, so move X2 into BX } mov [X1], bx { Move X2 into X1 } mov [X2], ax { Move X1 into X2 } mov ax, [Y1] { Move Y1 into AX } mov bx, [Y2] { Move Y2 into BX } mov [Y1], bx { Move Y2 into Y1 } mov [Y2], ax { Move Y1 into Y2 } mov [IncF], 320 { Move 320 into IncF, ie, next pixel is on next row } mov ax, [Y1] { Move Y1 into AX } cmp ax, [Y2] { Compare Y1 to Y2 } jbe @SkipNegate2 { Was Y1 <= Y2 ? } @SkipNegate2: mov ax, [Y1] { Move Y1 into AX } mov bx, 320 { Move 320 into BX } mul bx { Multiply AX by 320 } mov di, ax { Move the result into DI } add di, [X1] { Add X1 to DI, giving us the offset } mov bx, [DeX] { Move DeX into BX } mov cx, bx { Move BX into CX } mov ax, 0A000h { Move the address of the VGA into AX } mov es, ax { Point ES to the VGA } mov dl, [Color] { Move the color to plot with in DL } mov si, [DeY] { Move DeY into SI } mov es:[di], dl { Put the byte in DL at ES:DI } inc di { Increment DI by one, the next pixel } sub bx, si { Subtract SI from BX } jnc @GoOn2 { Did it yield a negative result? } @GoOn2: loop @DrawLoop2 { Keep on plottin' } I don't think I made any mistakes with the commenting, but I am pretty tired,and I haven't handy any caffeine for days - let alone hours, so if you spot a I was going to include a Circle algorithm, but I couldn't get mine to workin Assembler - all the floating point math might have something to do with it. I could include one written in a high level language, but this is meantto be an Assembler tutorial, not a graphics one. However, if enough people ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ ³ THE INS AND OUTS OF IN AND OUT ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ IN and OUT are a very important part of Assembler coding. They allow you to directly send/receive data from any of the PC's 65,536 hardware ports, orregisters. The basic syntax is as follows: þ IN <ACCUMULATOR>, <PORT> - Name: Input from I/O port Type: 8086+ value from one of the 65536 hardware ports into the specified accumulator.
ports, and DX is commonly used to identify the port.
þ OUT <PORT>, <ACCUMULATOR> - Name: Output to Port Description: This instruction outputs the value in the accumulator to <PORT>. Using the DX register to pass the port to OUT, you may access up to 65,536 ports.
Okay, that wasn't very helpful, as it didn't tell you much about how to useit - let alone what to use it for. Well, if you intend to work with the VGA much, you'll have to be able to program its internal registers. Similar tothe registers that you've been working with up until now, you can think of changing them just like interrupts, except: 1) You pass the value to theport, and that's it; and 2) It is pretty near instantaneous.
As an example, we'll cover how to set and get the palette by directly Now, the VGA has a lot of registers, but the next three you'd better get to þ 03C7h - PEL Address Register (Read) Sets the palette in read mode þ 03C9h - PEL Data Register (Read/Write) Read in, or write 3 RGB values, every 3rd write, the index, or color you are setting, is incremented by one.
If we were to set a color's RGB value, we'd send the value of the color wewanted to change to 03C8h, then read in 3 values from 03C9h. In Assembler, mov dx, 03C8h ; Put the DAC read register in DX mov al, [Color] ; Put the color's value in AL out dx, al ; Send AL to port DX inc dx ; Now use port 03C9h mov al, [R] ; Put the new RED value in AL out dx, al ; Send AL to port DX mov al, [G] ; Put the new GREEN value in AL out dx, al ; Send AL to port DX mov al, [B] ; Put the new BLUE value in AL out dx, al ; Send AL to port DX And that would do things nicely. To read the palette, we'd do this: mov dx, 03C7h ; Put the DAC write register in DX mov al, [Color] ; Put the color's value in AL out dx, al ; Send AL to port DX in al, dx ; Put the value got from port DX in AL les di, [R] ; Point DI to the R variable - this came from Pascal in al, dx ; Put the value got from port DX in AL les di, [G] ; Point DI to the G variable in al, dx ; Put the value got from port DX in AL les di, [B] ; Point DI to the B variable Note how that routine was coded differently. This was originally a Pascal routine, and as Pascal doesn't like you messing with Pascal variables inAssembler, you have to improvise.
If you are working in stand alone Assembler, then you can code this much more efficiently, like the first example. I left the code as it was so those whoare working with a high-level language can get around a particularly annoying Now you have seen how useful IN and OUT can be. Directly controlling hardwareis both fast and efficient. In the next few weeks, I may include a list of some of the most common ports, but if you have a copy of Ralf Brown'sInterrupt List, (available at X2FTP), you will already have a copy.
Note: You can find a link to Ralf's Interrupt List on my homepage.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Now, although we have been using the flags register in almost all our code up until this point, I haven't really gone into depth about it. You can workblissfully unaware of the flags, and compare things without knowing what's really happening, but if you want to get further into Assembler, you'llneed to know some more.
Back in Tutorial Three, I gave an extremely simplistic view of the FLAGS register. In reality, the FLAGS, or EFLAGS register is actually a 32-bitregister, although only bits 0-18 are used. We really don't need to know any of the flags above bit 11 for now, but it's good to know they are there.
The EFLAGS register actually looks like this: 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 AC VM RF -- NT IO/PL OF DF IF TF SF ZF -- AF -- PF -- CF þ VM - Virtual 8086 Mode þ RF - Resume Flag þ NT - Nested Task Flag þ IOPL - I/O Privilege Level - has a value of 0,1,2 or 3 thus 2 bits big This bit is set to ONE if an arithmetic instruction generated a result that was too large or too small to fit in the destination þ DF - Direction Flag When set to ZERO, string instructions, such as MOVS, LODS and STOS will increment the memory address they are working on by one.
This means that say, DI, will be incremented when you use STOSB to put a pixel at ES:DI. Setting the bit to ZERO will decrement the memory address after each call.
þ IF - Interrupt Enable Flag When this bit is set, the processor will respond to external hardware interrupts. When the bit is reset, hardware interrupts are ignored.
When this bit is set, an interrupt will occur immediately after the next instruction executes. This is generally used in debugging.
This bit is changed after arithmetic instructions. The bit receives the high-order bit of the result, and if set to ONE, it indicates that the result of the operation was negative.
þ ZF - Zero Flag This bit is set when arithmetic instructions generate a result of þ AF - Auxiliary Carry Flag This bit indicates that a carry out of the low-order nibble of AL occurred in an arithmetic instruction.
þ PF - Parity Flag This bit is set to one when an arithmetic instruction results in þ CF - Carry Flag This bit is set when the result of an arithmetic operation is too large or too small for the destination register or memory address.
Now, of all those above, you really won't have to worry too much about mostof them. For now, just knowing CF, PF, ZF, SF, IF, DF and OF will be sufficient. I didn't give the first few comments as they are fairlytechnical, and are used mostly in protected mode and complex situations. You You can, if you wish, move a copy of the flags into AH with LAHF - (Load AHwith Flags) - and modify or read individual bits, or change the status of bits more easily with CLx and STx. However you plan to change the flags,remember that they can be extremely useful in many situations.
(They can also be very annoying when late at night, lines start drawing backwards, and you spend an hour wondering why - then remember that youforgot to clear the direction flag!) ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ I think we've covered quite a few important topics in this tutorial. Brush up on the flags, and go over the largish line routine, as it is an excellentexample of flow control. Make sure your skills at controlling instruction Next week I'll try to tie all the topics we've covered over the last fewweeks together, and present some form of review of all that you've learnt.
Next week I'll also go into optimization, and how you can speed up all thecode we've worked with so far.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ þ A review of all you've learnt þ Optimization þ Declaring procedures in Assembler þ Linking your code to C/C++ or Pascal If you wish to see a topic discussed in a future tutorial, then mail me, and ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Don't miss out!!! Download next week's tutorial from my homepage at:

Source: ftp://ftp.univap.br/pub/manutencao/Drivers/CD_Rec_HDs_e_Outros/Cursos%20e%20Apostilas/ALLTUTS/ASMTUT06.pdf


The "Win-Win" initiative: a global, scientifically based approach to resource sparing treatment for systemic breast cancer therapy Ahmed Elzawawy 1,2,3,4,5 1Clinical Oncology Department, Faculty of Medicine, Suez Canal University, Egypt 2Alsoliman Radiation Oncology Unit, Port Said, Egypt 3Early Detection and Cancer Chemotherapy Unit, Port Said General Hospital, Egypt 4ICEDOC: Inte

Duncan dentures

Duncan Dentures Partial Dentures - Detachable partial dentures are oral prosthetics that can be utilized by individuals who have a few teeth missingon either the upper or lower arch. These dental devices are different than bridges or implants in that they are capable of beingextricated from the oral cavity. Their purpose is to interchange multiple missing teeth with a single simple dental devic

Copyright © 2014 Medical Pdf Articles