0

Write an assembler program that will perform the following operations:

  1. 01011011B and 11000111B
  2. 10110011B or 10111101B
  3. 01101001B xor 10101101B
  4. not 10011001B

Display the results of each operation as an ASCII string of binary digits with an appropriate message or header on a separate line before the results.

hint: USE SHL to isolate each bit and jump carry.
hint: Use the DOS 21h interrupt service, function 2 for the digits.

Can someone please explain what needs to be done? I am very new at this and can't get anything going. If I can see the first one I'm sure I could get the rest going, I hope. I 'm just not sure how the output should look. This is what I have so far and I'm sure I'm way off. Thank you and I really appreciate the help.

    .stack 100h

    .model small

    .386

    .data


    .code

main:

 MOV AX, @DATA                ; initialize DS
 MOV DS, AX


    mov al,01011011b                     
    mov cl,11000111b
    and ah, cl
    shl al, cl
    int 21h

 MOV AH, 2                    ; print the processed value of AL
 MOV DL, BL
 INT 21H

 MOV AH, 4CH                  ; return control to DOS
 INT 21H

 end main
lurker
  • 56,987
  • 9
  • 69
  • 103
Iceman
  • 35
  • 6
  • The hint meant you to use a loop to shift the value 8 times, each time shifting the most significant bit into the carry flag which you can then turn into ascii by adding the ascii code of 0 (which is 48). – Jester Feb 20 '15 at 17:56
  • Are there any good examples of this or a book. My class does not have a book but I refuse to give up? Thank you for your help! – Iceman Feb 20 '15 at 17:59
  • Can you add to a register, compare it to a constant and make a conditional jump? If so, you can make a loop. The `shl` is a given, and you can either add the ascii code or use a conditional jump to load '0' or '1'. The printing is a given. Need more hints? – Jester Feb 20 '15 at 18:02
  • The hints pretty much tell you what you need to do. The actual bitwise operation is easy, since there are instructions for those. The real work is displaying the operands and the results as binary strings, which means you need to take a number such as, `01011011b` in a register and spit it out as a string "01011011". You should write that as a subroutine and call it every time you want to print such a number. That's where the `SHL` comes in: to determine, in a loop, what the next bit is to print, and print a "0" or "1", in order. `DOS 21h` interrupt service to print a character. – lurker Feb 20 '15 at 18:03
  • Honestly no. the teacher gave us a boat and pushed us into the water without a paddle. We have never done anything to practice this that's why I'm interested in a good book or example. Our slides are poor and half the time the code never works. She can't even get the code to work. I will try and do what you suggested. I can loop but the comparing a register and jump???? – Iceman Feb 20 '15 at 18:07
  • I feel well not smart. this is only the 5th class in this should I know this by now??? – Iceman Feb 20 '15 at 18:09
  • 1
    If, in x86 assembly, you know how to move a number into a register, call a subroutine, shift bits, check for carry, and do a conditional jump, then that plus what the teacher told you is all you need to know to write the program. I assume your class has been about how to do some of those things, or the teacher expects you'll do some homework and read up on it. There are lots of x86 assembly example programs out there to help know how to do these kinds of operations. From your example, it looks like you know how to deal with the bitwise operations themselves. – lurker Feb 20 '15 at 18:21

2 Answers2

1

Here's an explanation of what needs to be done without writing the program out. Note that programming is initially about organizing your thoughts on the problem. You're being asked to perform some operations, and to provide specific output showing the results.

  1. Print "01011011B AND 11000111B results:\n" ["...an appropriate message or header on a separate line"]

  2. Perform 01011011B AND 11000111B in assembly

  3. Call subroutine to print the result of the operation

Repeat the above steps for the other operations (OR, XOR, NOT)

Your subroutine (in English, not structured exactly as you would in detail) for printing would be:

Repeat 8 times:

  1. Shift the next high order bit of 8-bit number into carry (use SHL)

  2. Jump if carry to 5

  3. Print a '0' [use DOS INT 21h service routine]

  4. Jump to 1

  5. Print a '1' [use DOS INT 21h service routine]

  6. Jump to 1

Then print a 'B' and then a carriage return

The output of the above would look like:

01011011B AND 11000111B results:
01000011B
10110011B OR 10111101B results:
10111111B
01101001B XOR 10101101B results:
11000100B
NOT 10011001B results:
01100110B

It's not that hard if you think through it. You can control the output format yourself. For example, you might want an extra carriage return after each result to give it some space. It's totally up to you and consistent with what it sounds like your teacher is requesting.

The nice way to do this would be to have the two numbers in a data memory location rather than hard-coding them. But it sounds like your teacher is willing to accept hard-coded.

lurker
  • 56,987
  • 9
  • 69
  • 103
  • Thank you for the help. What should the print look like that's what I don't get? What is the point of this? I feel stupid I'm sorry. – Iceman Feb 20 '15 at 18:52
  • @Iceman I added what the output might look like. It's totally under the control of your program. Don't feel stupid. You just need to think it through. :) – lurker Feb 20 '15 at 19:12
0

I could just write it for you but what's the fun in that? I'll teach you a little trick to get you started. Here's a loop that will print ANY 8-bit value as a binary string:

printBinAscii:
;input: al = the byte you wish to print.
mov cx,8

printBinAscii_again:
mov bh,'0'  ;mov bh,30h
shl al,1    ;shift the leftmost bit out of AL and into the carry flag.
adc bh,0    ;add the carry flag to BH. The result is the ASCII code for the bit we shifted out.
mov ah,2
mov dl,bh
int 21h
loop printBinAscii_again ;repeat 7 more times, until all the bits are printed.

This might be a bit confusing if you're new, but the reason this works is twofold:

  • ASCII codes are organized in a logical manner. All the digits 0-9 are represented by 0x30-0x39 as you would expect. So to convert a one-digit number to ASCII you just add 0x30.
  • The bit shift instructions use the carry flag to represent the bit that was "pushed out," and we can use adc 0 to conditionally add 1 if the carry was set. You could use a branch to do this, but it's much quicker to use adc 0.
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
puppydrum64
  • 1,598
  • 2
  • 15
  • Doesn't `int 21h` / `AH = 2` overwrite AL? Yeah, http://spike.scu.edu.au/~barry/interrupts.html#ah02 says it does (IIRC, DOS traditionally implemented that function with a BIOS `int 10h` that takes an arg in AL). Also, why are you using BH here, instead of just creating the ASCII digit in DL? Good explanation of why/how this works, though, so you just need a minor bugfix, perhaps taking input in BH or BL. – Peter Cordes Jul 22 '22 at 17:30
  • We have [Creating an x86 assembler program that converts an integer to a 16-bit binary string of 0's and 1's](https://stackoverflow.com/a/40811986) as a canonical answer about integer -> base 2 string. But a shorter one with an efficient loop would be good. There are several other Q&As where people have posted worse ones, e.g. branching on the low or high bit instead of using `adc` or `setc`. – Peter Cordes Jul 22 '22 at 17:58