Presentation is loading. Please wait.

Presentation is loading. Please wait.

Crafting a ‘demo’ program A ‘walk-through’ of the program development cycle for an example in assembly language.

Similar presentations


Presentation on theme: "Crafting a ‘demo’ program A ‘walk-through’ of the program development cycle for an example in assembly language."— Presentation transcript:

1 Crafting a ‘demo’ program A ‘walk-through’ of the program development cycle for an example in assembly language

2 Our purpose We want to illustrate the steps that a Linux program needs to take when modifying the normal ‘canonical mode’ terminal behavior We want to write it in assembly language Our Project #2 involves something similar Here we want to ‘Keep It Simple’ (KISS) But yet we want to show the essentials We might see new Pentium instructions

3 Just a tiny change Users can normally ‘cancel’ a program They can do it by typing -C It’s important for stopping “infinite loops” The system sends a ‘termination’ signal This avoids the need for a system ‘reboot’ But we can ‘reprogram’ this tty capability We just turn off a bit in the ‘c_lflag’ field

4 Our ‘nocbreak.s’ demo Step 1: get the terminal’s initial settings Step 2: save a copy of these settings Step 3: modify the ISIG bit in ‘c_lflag’ field Step 4: install the ‘modified’ tty settings Step 5: let user do some keyboard input Step 6: reinstall original terminal settings Step 7: Quit (i.e., return control to Linux)

5 Step 1: Get ‘tty’ settings We can use the ‘tcgetattr()’ function It’s part of the system’s runtime library Use ‘man’ command to see how it’s called Here’s its function prototype: int tcgetattr( int fileno, struct termios &tty ); We can call it using assembly language: –Push the arguments (in right-to-left order) –Call the function:calltcgetattr –Discard the arguments from the stack

6 Here’s the code.section.data ttywrk:.space60# for ‘termios’ object.section.text pushl$ttywrk# push the address pushl$0# push device-ID calltcgetattr# call runtime library addl$8, %esp# discard arguments

7 Step 2: copy the object We can setup a loop to perfortm copying Loop can copy structure one byte at a time Total number of bytes is loop-count (60) Put source-address into a cpu register Put dest’n-address into a cpu register Advance addresses as each byte is copied Use ‘loop’ opcode to decrement-and-jump

8 Here’s the data.section.data ttysav:.space60# original structure ttywrk:.space60# our working copy

9 And here’s the code.section.text movl$ttywrk, %esi# setup source addr movl$ttysav, %edi# setup dest’n addr movl$60, %ecx# setup loop-count nxmv:# label the loop-body movb(%esi), %al# copy src byte to AL movb%al, (%edi)# copy AL to dest’n incl%esi# advance src-addr incl%edi# advance dst-addr loopnxmv# finish coping bytes

10 Step 3: modify the flag-bit We know where the ‘c_lflag’ field is It’s starts 12 bytes into ‘termios’ structure We got this info from our ‘ttyinfo.cpp’ demo Similarly we can find that ISIG bit is bit #1 We want to “reset” this bit (i.e.,clear it to 0) We could use a bitwise AND operation But Pentium offers us another way (BTR)

11 Here’s the code.equ ISIG, 0 # symbolic constant.section.data ttywrk:.space 60# for termios object.section.text movl$12, (%edx)# offset for ‘c_lflag’ btr#ISIG, ttywrk(%edx) # resets bit #1

12 Brief digression Other Pentium bit-manipulations: BTS(bit-set) BTR(bit-reset) BTC(bit-complement) BT(bit-test) These operations all have this “side effect”: –the previous bit-value gets transferred to the CF-bit (Carry Flag) within the Pentium’s EFLAGS register Why? So you can use JC (or JNC) afterward

13 Step 4: Install new behavior We can use the ‘tcsetattr()’ function Use ‘man tcsetattr’ to see how its called Requires three function arguments: –Device’s ID-number (i.e., 0 for keyboard) –A flag-value, to specify buffer-flushing –The address of the new ‘termios’ object As usual, these arguments have to be pushed in reverse (i.e., right-to-left) order

14 Here’s the function-call.section.text pushl$ttywrk# address of the object pushl$TCSAFLUSH# flag-value pushl$0# keyboard’s device-ID calltcsetattr# call to runtime library addl$12, %esp# rebalance stack # NOTE: Similar code is used later in step 6

15 Step 5: Try new tty behavior We want to let the user type some input In particular, we want to test -C We’ve changed the normal tty handling Prove -C won’t stop the program Find out what the new response will be We need program to ‘read’ from keyboard Can use ‘read()’ from the runtime library

16 How ‘read()’ works Function’s prototype shows 3 arguments: –Device ID-number (e.g., 0 for the keyboard) –Address for an input-buffer (we create buffer) –Maximum number of bytes that will be read In canonical mode, the ‘read()’ call won’t return until either the user hits or the maximum number of bytes have been transferred into the input-buffer

17 So here’s the ‘read()’ call.section.data inchar:.space1# room for 1 byte.section.text pushl$1# maximum bytes pushl$inchar# buffer’s address pushl$0# keyboard’ ID callread# call to C library addl$12, %esp# discard arguments

18 Testing for -code We needed a way to stop the program Can’t quit by using -C now Our solution: quit by hitting So program needs to test for its ascii-code ASCII-code for ESCAPE-key equals 0x1B Our loop includes a compare-and-branch

19 Testing for the ‘exit’ condition.section.data inchar:.space1# buffer for user input.section.text again: … cmpb$0x1B, inchar# user typed ESC? jneagain# no, reenter loop # otherwise, fall through to next instruction

20 A ‘tweak’ for esthetics When we tested our ‘nocbreak’ demo, we did not like the screen’s appearance Our program’s final output was ‘garbled’ by the subsequent command-shell prompt We wanted to make the output prettier So we added a additional code-fragment A ‘newline’ control-code gets printed after each keypress by the user (using ‘write()’)

21 In-class exercises Programmers can choose among several ways of accomplishing a particular task Example: there’s more than one way to copy a 60-byte data-structure from one place in memory to another We don’t have to do it one-byte-at-a-time We don’t have to use both %esi and %edi Try doing the copying in some other ways

22 Using a common array-index Here’s an idea for a different copying scheme.section.text xorl%esi, %esi# array-index movl$30, %ecx# word-count nxwm: movwttywrk(%esi), %ax # fetch word movw%ax, ttysav(%esi) # store word addl$2, %esi # next word index loopnxwm

23 Using a ‘scaled’ array-index # we use a ‘scaled index’ to do array-addressing.section.text xorl%esi, %esi# clear to zero movl$30, %ecx# loop-count nxwd: movwttywrk(, %esi, 2), %ax movw%ax, ttysav(, %esi, 2) incl%esi # increment index loopnxwd:

24 Exercise Try to devise the ‘most efficient’ method you can think of for copying the 60-bytes But what does ‘most efficient’ mean? –Using the fewest assembly statements? –Using the fewest cpu regisers? –Executing the fewest loop-iterations? Will your “solution” be the same no matter what you think “most efficient” means?


Download ppt "Crafting a ‘demo’ program A ‘walk-through’ of the program development cycle for an example in assembly language."

Similar presentations


Ads by Google