Lecture 5 Interrupts in Turbo C Concepts of

Lecture 5: Interrupts in Turbo C++ § Concepts of Interrupts § Programs for interrupts: l l l Keyboard Video Time 1 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Execution of an Instruction (review) Execution of an instruction is achieved by a sequence of commands issues by the control unit. Fetch the instruction from the memory Fetch the operands from the memory Perform the operation Update the program counter no Next Instruction 9/6/2021 Check interrupt yes Interrupt processing CS 3369 Real Time Control Software/DENG Xiaotie 2

Execution of a Program (review) Fetch the instruction from the memory Fetch the operands from the memory Perform the operation Update the program counter A program is a sequence of instructions. no LOAD b, R 1 Check interrupt yes Fetch the instruction from the memory Fetch the operands from the memory Perform the operation Update the program counter no Check interrupt yes ADD R 1, 1 a = b + 1; Fetch the instruction from the memory Fetch the operands from the memory Perform the operation Update the program counter no 9/6/2021 STORE R 1, a Check interrupt yes …. . . CS 3369 Real Time Control Software/DENG Xiaotie 3

Interrupt • Interrupt is a mechanism for diverting the attention of a processor when a particular event occurs, such as I/O device requests. • Interrupts cause a break in the normal execution of a program. 4 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

A Break in the Normal Execution of a Program Fetch the instruction from the memory Interrupt Fetch the operands from the memory Perform the operation Update the program counter no The execution of the program can be temporarily stopped to allow a special piece of software -- an interrupt service routine -to run. When the routine has finished, the program resumes. Check interrupt yes Fetch the instruction from the memory Fetch the operands from the memory Perform the operation Update the program counter no Check interrupt yes Interrupt processing + efficient and responsive - difficult to program 9/6/2021 Interrupt Processing and Service 5 CS 3369 Real Time Control Software/DENG Xiaotie

Steps taken to process Interrupt 1. On receipt of the interrupt, the processor after executing the current instruction, branches to an interrupt processing routine. The routine is commonly known as Interrupt Handler. 2. The Interrupt Handler will save the current processor data (registers, status register, PC) and determine which device has interrupt the processor (polling). 3. Execution then branches to the so called Interrupt Service Routine associated with the device (causing the interrupt) and the processor executes data transfer. 4. The interrupt system is enable so that further interrupts may be recognized. 5. Return to that program the execution of which was suspended after recognizing the interrupt. 6 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Interrupt Processing and Service Disable interrupts Save environment Find out which device causes interrupt Branch to specific interrupt service routine ISR 1 ISR i ISR n Restore environment Enable interrupts 7 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Interrupt Vectors the segmented addresses that specify the locations of interrupt handlers are called interrupt “vectors” • • an interrupt handler is a function/subroutine that takes care of the interrupt. • There are 256 interrupt vectors stored in interrupt vector table located at the beginning of the memory • some are reserved and some can be used by users 8 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Types of Interrupt • Hardware Interrupts • CPU Interrupts • Software Interrupts 9 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Hardware Interrupts Hardware interrupts are generated by device control and supervised by PIC (programmable interrupt control) chip. Interrupt No. Functions § § § § 0 x 02 0 x 08 0 x 09 0 x 0 A 0 x 0 B, 0 x 0 C 0 x 0 D 0 x 0 E 0 x 0 F NMI: non-maskable interrupt, memory parity timer (18 per second) keyboard interrupt from controller 2 serial port 2, 1 parallel port 2 diskette parallel port 1 (for printer) Here, NMI has top priority and is serviced immediately, and it cannot be turned off. It occurs due to some significant error, such as power failure. HERE: 0 x stands for hexadecimal notations: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, where A stands for ten, B eleven, C, twelve, D thirteen, E fourteen, F fifteen. Therefore, 0 x 200 is 2 x 16 plus 0 which is 512 in decimal. For decimal notations: 200=2 x 10. 10 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

CPU Interrupts CPU interrupts are generated in response to a fatal program error, or for program flow control § 0 x 00 § 0 x 01 instruction § 0 x 02 user § 0 x 04 division by zero generated after every when in single-step mode generated when a program reaches a breakpoint set by arithmetic overflow 11 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Software Interrupts Software interrupts are generated by using the software interrupt instruction. In turbo C: #include <dos. h> geninterrupt(n); § BIOS interrupts: provides the most direct, low level interaction with the I/O devices and give a deviceindependent interface which hides all the details of the hardware architecture from programmers and includes interrupt numbers: 0 x 05, 0 x 10 -0 x 1 C, 0 x 48. § DOS interrupts: are parts and the DOS operating system, handle file and memory management and executive services: 0 x 20 -0 x 60 § General use interrupts: can be written by users for their own service routines: 0 x 61 -0 x 67 Notice: no need to remember all the interrupt vectors. 9/6/2021 Focus on 12 CS 3369 Real Time Control Software/DENG Xiaotie

A Register INPUT OUTPUT Q D CLOCK D: data input Q: output of data in the register 13 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Architecture of PC Registers Scratch-pad Registers § § § § AX (accumulator) BX (base) CX (count) DX (data) CS (code segment) DS (data segment) SS (stack segment) ES (extra segment) IP (instruction pointer) SP (stack pointer) BP (base pointer) SI (source index) DI (destination index) Flags AH BH CH DH 7 OF DF 0 7 AL BL CL DL 0 15 Segment Registers 0 15 Offset Registers 0 IF TF SF ZF AF PF CF 14 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Access Registers in Turbo C REGISTERS • • • • AX BX CX DX CS DS SS ES SP BP SI DI Flags PSUDO-VARIABLES in C _AX (_AH _AL) _BX (_BH, _BL) _CX (_CH, _CL) _DX (_DH, _DL) _CS _DS _SS _ES _SP _BP _SI _DI _FLAGS 15 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

The Flag Register in IBM PC 15 0 OF DF IF TF SF ZF AF PF CF IF is the interrupt flag which controls whether interrupts are enabled. IF=1: The CPU will deal with interrupt requests. IF=0: The CPU will ignore interrupt requests. CF Carry flag Indicates an arithmetic carry OF Overflow flag Indicates a signed arithmetic overflow ZF Zero flag Indicates a zero result or an equal comparison SF Sign flag Indicates a negative result or comparison PF Parity flag Indicates an even number of 1 bits AF Auxiliary carry flag …. DF Direction flag Controls increment direction in string operastions TF Trap flag Controls single-step operation (used by DEBUG). 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie 16

BIOS Keyboard Services They are invoked with interrupt 0 x 16 with the following Service numbers in the register AH (_AH in Turbo C). service# functionality § § § § 0 x 00 0 x 01 0 x 02 0 x 03 0 x 05 0 x 10 0 x 11 0 x 12 Read Next Keyboard Character Report Whether Character Ready Get Shift Status Set Typematic Rate and Delay Keyboard Write Extended Keyboard Read Get Extended Keystroke Status Get Extended Shift Status Notice: 1. Service numbers are parameters pass to the subroutines/interrupt handlers 9/6/2021 2. Try to remember the meaning of service 0 x 00 and 0 x 01 for interrupt 0 x 16. CS 3369 Real Time Control Software/DENG Xiaotie 17

Interrupt 0 x 16 Service 0 x 00 reports the next keyboard input character. If there is no character in the BIOS keyboard buffer, it waits until one is ready. The character is removed from the BIOS keyboard buffer after it is read. § Each character is reported as a pair of bytes. The main byte returned in AL is either 0 for special characters, or an ASCII code for ASCII characters. § The auxiliary byte returned in AH is either the character ID for special characters or the standard PC-keyboard scan code identifying the pressed key. To invoke this service to read a character into a variable x in Turbo C, we do: char x; _AH=0 x 0; geninterrupt(0 x 16); x=_AL; 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie 18

An Example of Getting a Key from Keyboard § § § char x; int y; _AH=0 x 0; geninterrupt(0 x 16); x=_AL; cout <<“The key is: ”<< x <<endl; § § § declare x to be “char” type choose service 0 x 0 with _AH invoke interrupt 0 x 16 get ASCII code of key from _AL print the key out Remember to include dos. h in your file. 19 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

A Function to get a key § char get_key_number () { l char a; l _AH=0 x 00; l geninterrupt(0 x 16); l a=_AL; l return tmp; l } //return type of the function is char //service number 0 x 00 //interrupt 0 x 16 //_AL is the key //return the value Demo the program A: key. cpp in the lecture. 1. Show the program 2. Run the program 20 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Interrupt 0 x 16 Service 0 x 01 tests whether a keyboard input character is ready. The zero flag (ZF) is used as the signal: 1 indicates no input is ready, 0 indicates a character is ready. In the latter case, the character is not removed from the BIOS keyboard buffer until it is read by service 0 x 00. To invoke this service in Turbo C, we do: char x; _AH=0 x 01; geninterrupt(0 x 16); To test whether a character is ready after the above steps in Turbo C, we do: if (_FLAGS&0 x 40==64); to check whether ZF is 1. 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie 21

Use Keyboard BIOS to Read § To write a program to read a char from BIOS keyboard buffer, one may first use service 0 x 01 interrupt 0 x 16 to test whethere is a key stored in the BIOS buffer, then use service 0 x 00 interrupt 0 x 16 to read it. l int ch; _AH=0 x 01; geninterrupt(0 x 16); temp=_FLAGS&0 x 40; l /*must put the data to temp, see slide 32 */ l l 9/6/2021 l The difference is that the computer does not have to wait for users to type it. if (temp==0) { – _AH=0; – geninterrupt(0 x 16); – ch=_AL; } CS 3369 Real Time Control Software/DENG Xiaotie 22

Caution when using Pseudo-Variables Pseudo-variables refer to CPU registers which are used by other programs which may run at the same time. One must assign values right before using them and read values right after obtaining them, especially when we program in C. Be careful about the following: § A pseudo-variable has no address § The values one place in pseudo-variables may NOT be preserved for any length of time. § Values of pseudo-variables may not remain the same across a function call. § Do not change values of _CS, _SP, nor _BP since they are used by machine code produced by Turbo C compiler. 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie 23

Write a function to get a character l int key_ready() {//return 1 if a key is ready, 0 otherwise • • • l l long int x; _AH=1; geninterrupt(0 x 16); x=_FLAGS; if (x&0 x 40==0) {return 1; } else return 0; } char read_a_key() { //service number 0 x 01 //interrupt 0 x 16 //get flag register //if ZF==0 a key is ready //else no key //return char if a key is ready • if (key_ready()) • {return get_key_number(). x; } • else return 0; l } 24 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Shoot a bullet when press a key #include<dos. h> #include <graphics. h> #include<iostream. h> #include<conio. h> void show(int i, float h, float v); void erease(int i, float h, float v); void main(void) { int driver = DETECT, mode; int i, j, i 1, s 1; int y=1; initgraph(&driver, &mode, "D: \bc 31\bgi"); setcolor(WHITE); line(1, 400, 400); for ( i = 0; i < 80; i++ ) { show(i, 5. 0, 9. 0); y=1; _AH=0 x 01; geninterrupt(0 x 16); // y=_FLAGS&0 x 40; if(y == 0) {s 1=1; i 1=i; _AH=0 x 00; geninterrupt(0 x 16); } if (s 1==1) {show(i-i 1, 10. 0, 8. 0); } delay (300); erease(i, 5. 0, 9. 0); if (s 1==1) erease(i-i 1, 10. 0, 8. 0); } closegraph(); } void show(int i, float h, float v) { int x, y; x=h*i; y=v*i-0. 15*i*i; setcolor(RED); circle(400 -x, 400 -y, 2); } void erease(int i, float h, float v) { int x, y; x=h*i; y=v*i-0. 15*i*i; setcolor(BLACK); circle(400 -x, 400 -y, 2); } 25 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Video Interrupt Services(for general knowledge, will not be tested) Most of the useful video services are found in the BIOS through interrupt 0 x 10. Some MS-DOS video services are provided through interrupt 0 x 21. They are user programmed interrupts to produce output to the video screen. Usually, one puts the function/service number in the register AH and then invokes the corresponding interrupt. Very often there are some parameters for these functions/services which are put in register AL, BX, CX, or DX. 26 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

BIOS Video Service Interrupt 0 x 10 service# functionality § § § 9/6/2021 0 x 00 0 x 01 0 x 02 0 x 03 0 x 04 0 x 05 0 x 06 0 x 07 0 x 08 0 x 09 0 x 0 A 0 x 0 B service# functionality set video mode set cursor size set cursor position read light-pen position set active display page scroll window up scroll window down read character/attribute write character set 4 -color palette • • • 0 x 0 C write pixel 0 x 0 D read pixel 0 x 0 E write char in tty mode 0 x 0 F get current video mode 0 x 10 color palette interface 0 x 11 char generator interface 0 x 12 alternate select 0 x 13 write character string 0 x 14/15 (PC convertible only) 0 x 1 A read/wri. dsp. cmb. code 0 x 1 B return functionality 0 x 1 C save/restore video state CS 3369 Real Time Control Software/DENG Xiaotie 27

Interrupt 0 x 10 Service 0 x 0 E: Write char in TTY mode § The. service number 0 x 0 E is put in register AH. § The char to be written is put in AL. The display page number is put in BH and the foreground color is in BL. § The character is written at the cursor location, and the cursor is advanced one position, wrapping over to new line or scrolling the screen as needed. § There are four characters that service 0 x 0 E reacts to according to their ASCII meaning: 0 x 07 beep, 0 x 08 backspace, 0 x 0 A linefeed, 0 x 0 D carriage return. All other characters are displayed normally. 28 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Output Characters Display character “a” § § _AH=0 x 0 E; _AL=97; _BH=1; geninterrupt(0 x 10); Feed a new line • • Back one space • • _AH=0 x 0 E; _AL=0 x 08; _BH=1; geninterrupt(0 x 10); _AH=0 x 0 E; _AL=0 x 0 A; _BH=1; geninterrupt(0 x 10); Beep • • _AH=0 x 0 E; _AL=0 x 07; _BH=1; geninterrupt(0 x 10); 29 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

A Function for Output a Char § void output_a_char(int x) { l l § } //x is the ASCII code of char _AH=0 x 0 E; _AL=x; _BH=1; geninterrupt(0 x 10); Call the function to output characters • • output_a_char(97); output_a_char(8); output_a_char(7); output_a_char(0 x 0 A); //output ‘A’ //backspace //output a ring //a new line 30 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Another Function for Output a Char § void output 2_a_char(char x) { l l l int tmp; tmp=x; _AH=0 x 0 E; _AL=tmp; _BH=1; geninterrupt(0 x 10); //x is a char type //convert to ASCII code //service number 0 x 0 E //output tmp //interrupt 0 x 10 § } Call the function to output characters • output 2_a_char(‘A’); • output 2_a_char(‘B’); //output “A” //output “B” 31 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Time Services (Clock) § Interrupt 0 x 21 Service 0 x 2 C: l CH contains the hours (0 -23) l CL contains the minutes (0 -59) l DH contains the seconds (0 -59) l DL contains hundredths of a second (0 -99). 32 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Time Services (Clock) § § § int i, j, k, l; _AH=0 x 2 C; //service 0 x 2 C for get time interrupt(0 x 21); //interrupt 0 x 21 i=_CH; j=_CL; k=_DH; l=_DL; cout<<i<<“ Hours”<<j<<“ Minutes ”<<k<<“ Seconds ”<<l; 33 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Get the Time of Hitting a Key Using the above functions written with interrupts, we may obtain the approximate time of hitting a key as follows: int i, j, k, l; read_a_key(); /*call function read_a_key(); */ _AH=0 x 2 C; //service 0 x 2 C for get time interrupt(0 x 21); //interrupt 0 x 21 i=_CH; j=_CL; k=_DH; l=_DL; cout<<i<<“ Hours”<<j<<“ Minutes ”<<k<<“ Seconds ”<<l; 34 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Arrays § An array is a collection of two or more adjacent memory cells, called array elements, that are associated with a particular symbolic name. To declare an array int x[3]; x[0] x[1] 9/6/2021 (We declared an array with name x. It contains 3 elements. Each is of int type. The index starts with 0) x[2] 35 CS 3369 Real Time Control Software/DENG Xiaotie

Use an array in the program § include <iostream. h> The index of the elements can change. The index of the first element of an array is 0. void main(void) { int x[10], i; for (i=0; i<=9; i++) cin>>x[i]; x[0], x[1], x[2], x[3], x[4] x[5], x[6], x[7], x[8], x[9] for (i=0; i<=9; i++) cout<< x[i]; } 36 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie
![Initialize an array § include <iostream. h> void main(void) { int x[10]={1, 2, 2, Initialize an array § include <iostream. h> void main(void) { int x[10]={1, 2, 2,](http://slidetodoc.com/presentation_image_h2/8aae20db34f9ccde7f62279f6fca5d6b/image-37.jpg)
Initialize an array § include <iostream. h> void main(void) { int x[10]={1, 2, 2, 2, 3, 4, 5, 6, 7, 9} , i; for (i=0; i<=9; i++) cout<< x[i]<<“ ”; } 37 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie
![An array of characters include <iostream. h> void main(void) { char x[3]={‘a’, ‘b’, ‘c’} An array of characters include <iostream. h> void main(void) { char x[3]={‘a’, ‘b’, ‘c’}](http://slidetodoc.com/presentation_image_h2/8aae20db34f9ccde7f62279f6fca5d6b/image-38.jpg)
An array of characters include <iostream. h> void main(void) { char x[3]={‘a’, ‘b’, ‘c’} , i; for (i=0; i<=9; i++) cout<< x[i]; } 38 9/6/2021 CS 3369 Real Time Control Software/DENG Xiaotie

Exercise What does the following program output? include <iostream. h> void main(void) { int x[10]={8, 7, 9, 10, 1, 3, 3, 8, 2, 5} , i, j; for (i=0; i<=9; i++) { for(j=9; j>i; j--) if (x[i]>x[j]) { y=x[i]; x[i]=x[j]; x[j]=y; } for(j=0; j<=9; j++) cout<< x[j]; cout<<“n”; } } 9/6/2021 39 CS 3369 Real Time Control Software/DENG Xiaotie

Shoot bullets whenever press key #include<dos. h> #include <graphics. h> #include<conio. h> void show(int i, float h, float v); void erease(int i, float h, float v); void planeshow(int i); void ereasep(int i); void main(void) { int driver = DETECT, mode; int i, j, i 1, s 1, k; int y=1; int a[100]; for(i=0; i<=99; i++) a[i]=0; initgraph(&driver, &mode, "D: \bc 31\bg i"); setcolor(WHITE); line(1, 400, 400); j=1; for ( i = 0; i < 80; i++ ) { setcolor(BLUE); planeshow(5*i); setcolor(YELLOW); planeshow(5*(i-8)); show(i, 5. 0, 9. 0); 9/6/2021 y=1; _AH=0 x 01; geninterrupt(0 x 16); // y=_FLAGS&0 x 40; if(y == 0) {j=j+1; a[j]=i; _AH=0 x 00; geninterrupt(0 x 16); } for (k=2; k<=j; k++) if (a[k]!=0) {show(i-a[k], 10. 0+0. 5*k, 8. 0+0. 1*k); } delay (300); ereasep(5*i); ereasep(5*(i-8)); erease(i, 5. 0, 9. 0); for (k=2; k<=j; k++) if (a[k]!=0) {erease(i-a[k], 10. 0+0. 5*k, 8. 0+0. 1*k); } } closegraph(); } void show(int i, float h, float v) { int x, y; x=h*i; y=v*i-0. 15*i*i; setcolor(RED); circle(400 -x, 400 -y, 2); } CS 3369 Real Time Control Software/DENG Xiaotie +plane void erease(int i, float h, float v) { int x, y; x=h*i; y=v*i-0. 15*i*i; setcolor(BLACK); circle(400 -x, 400 -y, 2); } void planeshow(int i) { int j; circle(i+5, 202, 2); circle(i+3, 204, 2); for (j=0; j<=8; j++) circle(i+j, 200, 2); circle(i+5, 198, 2); circle(i+3, 196, 2); } void ereasep(int i) { int j; setcolor(BLACK); circle(i+5, 202, 2); circle(i+3, 204, 2); for (j=0; j<=8; j++) circle(i+j, 200, 2); circle(i+5, 198, 2); circle(i+3, 196, 2); } 40

a-shoot bullet #include<dos. h> #include <graphics. h> #include<conio. h> void show(int i, float h, float v); void erease(int i, float h, float v); void planeshow(int i, int k); void ereasep(int i, int k); void main(void) { int driver = DETECT, mode; int i, j, i 1, s 1, k; int y=1, xx=0; char x; int a[100]; for(i=0; i<=99; i++) a[i]=0; initgraph(&driver, &mode, "a: \bgi"); setcolor(WHITE); line(1, 400, 400); j=1; for ( i = 0; i < 80; i++ ) { setcolor(BLUE); planeshow(5*i, 5); show(i, 5. 0, 9. 0); y=1; _AH=0 x 01; geninterrupt(0 x 16); y=_FLAGS&0 x 40; 9/6/2021 u-plane up i-plane down if(y == 0) { _AH=0 x 00; geninterrupt(0 x 16); x=_AL; if (x == 'a') {j=j+1; a[j]=i; } if (x =='u' ) {sound(700); xx=xx-5; } if (x =='i' ) {sound(200); xx=xx+5; } } setcolor(YELLOW); planeshow(5*(i-8), xx); for (k=2; k<=j; k++) if (a[k]!=0) {show(i-a[k], 10. 0+0. 5*k, 8. 0+0. 1*k); } delay (300); nosound(); ereasep(5*i, 5); ereasep(5*(i-8), xx); erease(i, 5. 0, 9. 0); for (k=2; k<=j; k++) if (a[k]!=0) {erease(i-a[k], 10. 0+0. 5*k, 8. 0+0. 1*k); } } closegraph(); } void show(int i, float h, float v) { int x, y; x=h*i; y=v*i-0. 15*i*i; setcolor(RED); circle(400 -x, 400 -y, 2); } CS 3369 Real Time Control Software/DENG Xiaotie void erease(int i, float h, float v) { int x, y; x=h*i; y=v*i-0. 15*i*i; setcolor(BLACK); circle(400 -x, 400 -y, 2); } void planeshow(int i, int k) { int j; circle(i+5, 202+k, 2); circle(i+3, 204+k, 2); for (j=0; j<=8; j++) circle(i+j, 200+k, 2); circle(i+5, 198+k, 2); circle(i+3, 196+k, 2); } void ereasep(int i, int k) { int j; setcolor(BLACK); circle(i+5, 202+k, 2); circle(i+3, 204+k, 2); for (j=0; j<=8; j++) circle(i+j, 200+k, 2); circle(i+5, 198+k, 2); circle(i+3, 196+k, 2); } 41
- Slides: 41