1

For the following example, using x86 code in AT&T format:

xor $0x20, (%eax) 
and $0x20, %ah 
or $0x20, %dh 
dec (%edi) 
dec %si
dec %sp
dec %bp

My understanding:

Line 1: takes value in %eax and does an XOR operation with 0x20

Line 2: takes value in %ah and dies an AND operation with 0x20

Line 3:  takes value in %dh and does an OR operation with 0x20.

Line 4: decrements value in %edi by 1

Line 5: decrements value in %si by 1

Line 6: decrements value in %sp by 1

Line 7: decrements value in %bp by 1

Questions:

  1. What happens to the result after each step of code has been run?

  2. Does the order of the operands matter? If yes why?

  3. How do you construct some equivalent code (e.g. decompile into c++) from this assembly code?

This is not a homework question - I am new to assembly. Example code is not from actual code - it's to help me get a better understanding & illustrate my questions.

  • 2
    something does not seem quite right about those offsets – julian Feb 14 '17 at 4:25
  • 1
    Where are the arguments? – ysap Feb 14 '17 at 9:49
  • 1
    @unseen_rider This article may help you with some of the terminology: Instructions, Operands, and Addressing. Are you interested in any particular instruction set? x86 for example – julian Feb 14 '17 at 14:54
  • 1
    As the article @SYS_V links to suggests, you should rename these to "operands" rather than "arguments". By "arguments" one usually means the input given to a function, and since you're asking about C++, your intention is unclear. – ysap Feb 14 '17 at 15:00
  • 1
    If you're trying to double-check your understanding of provided code, perhaps share your thoughts and let us correct you instead of providing you with the answers? – NirIzr Feb 14 '17 at 22:37
3

Note: this answer corresponds to the original question.

I am new to assembly as well so I can see where you are coming from. With that being said, there seem to be quite a few issues with the contrived code that you have posted.

Does the order of the operands matter? If yes why?

There are two different styles of human-readable mnemonics used to represent CPU instruction codes: AT&T and Intel. While the order the operands are shown in is different between Intel and AT&T syntax, the order of instruction code bytes in memory is constant.

Intel syntax:

08048074 <main>:
 8048074:       55                      push   ebp
 8048075:       89 e5                   mov    ebp,esp
 8048077:       b8 00 00 00 00          mov    eax,0x0
 804807c:       5d                      pop    ebp
 804807d:       c3                      ret    

AT&T syntax:

08048074 <main>:
 8048074:       55                      push   %ebp
 8048075:       89 e5                   mov    %esp,%ebp
 8048077:       b8 00 00 00 00          mov    $0x0,%eax
 804807c:       5d                      pop    %ebp
 804807d:       c3                      ret  

The (little-endian) byte sequence 89 e5 is represented as mov ebp,esp in Intel syntax and as mov %esp,%ebp in AT&T syntax. Though the mnemonic representations of the operands are opposite of each other, they represent the same byte sequence. The order of the opcode mnemonics matters in that it is determined by the syntax used to represent the instruction codes.

The code

What happens to the result after each step of code has been run?

Every line of the code posted in the question except the last contains at least one illegal operand so only that line could feasibly run.

AT&T syntax is assumed.

0x2000: cs cs cs

  • %cs is a segment register and, being a register, must be prefixed with the % symbol. There are 3 operands here that are all the same register and no instruction. This is illegal. I am not sure what you envisioned would happen here.

0x2001: xor x20,(eax)

  • x20 is an illegal operand. Constants are immediate operands which must be prefixed with the $ symbol, so this operand should be $0x20. %eax is a register, hence the % prefix is required. (eax) should instead be (%eax).

0x2002: and x20,%ah

  • x20 should be $0x20

0x2003: or x20, %dh

  • x20 should be $0x20

0x2004: dec (ebi)

  • ebi looks like it is supposed to be a register. Did you mean %edi or %ebx? Either way, it lacks the % prefix

0x2005: dec %si

  • The dec instruction decrements the contents of its operand by one. So the value stored in %si will be decremented.

Fixed up, the code would look like this:

xor $0x20, (%eax)
and $0x20, %ah
or  $0x20, %dh
dec (%edi)
dec %si

How do you construct some equivalent code (e.g. c++) from this assembly code?

Assuming that the corrected code is actually correct, someone with sufficient understanding could simply look at this snippet and create a roughly equivalent statement or sequence of statements in a high level language. For mere mortals, there are tools called decompilers.

Resources

Programming from the Ground Up by Jonathan Bartlett and "Professional Assembly Language" by Richard Blum are pretty good IMO. A more technical resource is the System V Application Binary Interface Intel386 Architecture Processor Supplement, which sheds light on some of the mysteries of the processor and virtual memory. SO's x86 wiki has a list of many resources. Of course, there are also the Intel manuals.

  • thanks for your answer. Very useful and helpful. I have updated my questions earlier following this, and have two more assembly lines of code at the bottom. - Do they decrement the base pointer and stack pointer values? What are the implications of this? What does the code do from a high level perspective? – unseen_rider Feb 16 '17 at 14:00
  • 1
    @unseen_rider the question is now so different from the original that the answer does not really reflect what is being asked. In a case like this my advise is to make a new question. Also, if you like a particular answer you should accept it – julian Feb 16 '17 at 14:29
  • Ok thank you. Have done. reverseengineering.stackexchange.com/questions/14682/… – unseen_rider Feb 18 '17 at 1:17
1

To answer your third question, from a computer science aspect c++ or any other highlevel language that isn't one to one mnemonic map of machine opcodes; soul purpose is to mitigate complexity. That being said c++ we can infer isn't or shouldn't be a 1 to 1 map to assembly. Some c syntax can't be exactly mapped.

For example a jump statement progresses the code to any other byte. So a jump can act like a conditional branch or a function call, etc. All very different statements in c++ yet they use the key part, jump instruction.

I think a better approach would be to ask how a c++ basic statements compile to assembly. If you understand and know thoughs it then is a simple thing to find those blocks in assembly.

note In modern setting most high level languages don't compile to x86 assembly but byte code or some operating specific format, often not far from assembly, however different enough that it requires the operating system to run. This is to abstract the underlying hardware so software doesn't have to get recompiled.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.