C increment/decrement operators [closed] - c

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
Determine the value of each variable after calculation is performed. All variables have value 5 before execution.
A1/=++B1/--C1
A2+=++B2%C2--
please tell me how this work

Variables:
int A1 = 5;
int B1 = 5;
int C1 = 5;
int A2 = 5;
int B2 = 5;
int C2 = 5;
Your code:
A1 /= ++B1 / --C1;
A2 += ++B2 % C2--;
Will probably compile into something similar too:
++B1;
--C1;
A1 /= B1 / C1;
++B2;
A2 += B2 % C2;
C2--;
You can output the ASM using your compiler, with GCC its the -S flag. Here is the ASM output with GCC on my computer (I added the comments):
movl $5, -20(%rbp) // A1 = 5
movl $5, -24(%rbp) // B1 = 5
movl $5, -28(%rbp) // C1 = 5
movl $5, -32(%rbp) // A2 = 5
movl $5, -36(%rbp) // B2 = 5
movl $5, -40(%rbp) // C2 = 5
Then for the first one calculation, this is performed (comments simplified for easier understanding):
addl $1, -24(%rbp) // ++B1
subl $1, -28(%rbp) // --C1
movl -24(%rbp), %eax //
cltd
idivl -28(%rbp) // divide B1 by C1
movl %eax, %esi //
movl -20(%rbp), %eax //
cltd
idivl %esi // divide A1 by the previous
movl %eax, -20(%rbp)

By the C Operator Precedence Table: http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm
For 1:
A1 /= ++B1 / --C1
C1 will first be decremented by 1 to 4
B1 will then be incremented by 1 to 6
B1 (6) will be divided by C1 (4), result of which will be 1
A1 will be assigned with the result of the division A1 (5) and 1, which is 5
Results for each will be 5, 6 and 4 for A1, B1 and C1, respectively.
For 2:
A2 += ++B2 % C2--
C2 will first be marked to get decremented close to the end of the statement, remains 5 for now
B2 will then be incremented by 1 to 6
The remainder from the division B2 (6) by C2 (5) will get calculated, which is 1
A2 will be assigned with the result of the addition of A2 (5) and 1, which is 6
C2 will be decremented by 1 to 4
Results for each will be 6, 6 and 4 for A2, B2 and C2, respectively.
Pardon me if I have made any mistakes, you can always check these with your compiler.

Related

Understanding function prologue with multiple function calls [duplicate]

This question already has answers here:
Why is there no "sub rsp" instruction in this function prologue and why are function parameters stored at negative rbp offsets?
(2 answers)
Why does the x86-64 GCC function prologue allocate less stack than the local variables?
(1 answer)
Closed 2 years ago.
Let's take the following example I have from a single function:
first_function:
pushq %rbp
movq %rsp, %rbp
movq $2, -8(%rbp)
movq $4, -16(%rbp)
...
pop %rbp
ret
If we look at the stack before the ..., it gives us:
>>> x/4g $rbp-16
0x7fffffffe410: 0x0000000000000004 0x0000000000000002
0x7fffffffe420: 0x0000000000000000 0x00000000004000bd
Or for me, an easier way to visualize it is:
+----------------+--------------------+---------------------------+
| 0x7fffffffe420 | 0x00000000004000bd | # function return address |
+----------------+--------------------+---------------------------+
| 0x7fffffffe418 | 0x0000000000000000 | # from push %rbp |
+----------------+--------------------+---------------------------+
| 0x7fffffffe410 | 0x0000000000000002 | # from mov $2, -8(%rbp) |
+----------------+--------------------+---------------------------+
| 0x7fffffffe408 | 0x0000000000000004 | # from mov $4, -16(%rbp) |
+----------------+--------------------+--------------------------
My question then is wouldn't a sub-function call (for example, if I called another function call in the ... section) possibly clobber all the two variables I've added above (2, and 4)?

COMISD not comparing properly [duplicate]

As part of a compiler project I have to write GNU assembler code for x86 to compare floating point values. I have tried to find resources on how to do this online and from what I understand it works like this:
Assuming the two values I want to compare are the only values on the floating point stack, then the fcomi instruction will compare the values and set the CPU-flags so that the je, jne, jl, ... instructions can be used.
I'm asking because this only works sometimes. For example:
.section .data
msg: .ascii "Hallo\n\0"
f1: .float 10.0
f2: .float 9.0
.globl main
.type main, #function
main:
flds f1
flds f2
fcomi
jg leb
pushl $msg
call printf
addl $4, %esp
leb:
pushl $0
call exit
will not print "Hallo" even though I think it should, and if you switch f1 and f2 it still won't which is a logical contradiction. je and jne however seem to work fine.
What am I doing wrong?
PS: does the fcomip pop only one value or does it pop both?
TL:DR: Use above / below conditions (like for unsigned integer) to test the result of compares.
For various historical reasons (mapping from FP status word to FLAGS via fcom / fstsw / sahf which fcomi (new in PPro) matches), FP compares set CF, not OF / SF. See also http://www.ray.masmcode.com/tutorial/fpuchap7.htm
Modern SSE/SSE2 scalar compares into FLAGS follow this as well, with [u]comiss / sd. (Unlike SIMD compares, which have a predicate as part of the instruction, as an immediate, since they only produce a single all-zeros / all-ones result for each element, not a set of FLAGS.)
This is all coming from Volume 2 of Intel 64 and IA-32 Architectures Software Developer's Manuals.
FCOMI sets only some of the flags that CMP does. Your code has %st(0) == 9 and %st(1) == 10. (Since it's a stack they're loaded onto), referring to the table on page 3-348 in Volume 2A you can see that this is the case "ST0 < ST(i)", so it will clear ZF and PF and set CF. Meanwhile on pg. 3-544 Vol. 2A you can read that JG means "Jump short if greater (ZF=0 and SF=OF)". In other words it's testing the sign, overflow and zero flags, but FCOMI doesn't set sign or overflow!
Depending on which conditions you wish to jump, you should look at the possible comparison results and decide when you want to jump.
+--------------------+---+---+---+
| Comparison results | Z | P | C |
+--------------------+---+---+---+
| ST0 > ST(i) | 0 | 0 | 0 |
| ST0 < ST(i) | 0 | 0 | 1 |
| ST0 = ST(i) | 1 | 0 | 0 |
| unordered | 1 | 1 | 1 | one or both operands were NaN.
+--------------------+---+---+---+
I've made this small table to make it easier to figure out:
+--------------+---+---+-----+------------------------------------+
| Test | Z | C | Jcc | Notes |
+--------------+---+---+-----+------------------------------------+
| ST0 < ST(i) | X | 1 | JB | ZF will never be set when CF = 1 |
| ST0 <= ST(i) | 1 | 1 | JBE | Either ZF or CF is ok |
| ST0 == ST(i) | 1 | X | JE | CF will never be set in this case |
| ST0 != ST(i) | 0 | X | JNE | |
| ST0 >= ST(i) | X | 0 | JAE | As long as CF is clear we are good |
| ST0 > ST(i) | 0 | 0 | JA | Both CF and ZF must be clear |
+--------------+---+---+-----+------------------------------------+
Legend: X: don't care, 0: clear, 1: set
In other words the condition codes match those for using unsigned comparisons. The same goes if you're using FMOVcc.
If either (or both) operand to fcomi is NaN, it sets ZF=1 PF=1 CF=1. (FP compares have 4 possible results: >, <, ==, or unordered). If you care what your code does with NaNs, you may need an extra jp or jnp. But not always: for example, ja is only true if CF=0 and ZF=0, so it will be not-taken in the unordered case. If you want the unordered case to take the same execution path as below or equal, then ja is all you need.
Here you should use JA if you want it to print (ie. if (!(f2 > f1)) { puts("hello"); }) and JBE if you don't (corresponds to if (!(f2 <= f1)) { puts("hello"); }). (Note this might be a little confusing due to the fact that we only print if we don't jump).
Regarding your second question: by default fcomi doesn't pop anything. You want its close cousin fcomip which pops %st0. You should always clear the fpu register stack after usage, so all in all your program ends up like this assuming you want the message printed:
.section .rodata
msg: .ascii "Hallo\n\0"
f1: .float 10.0
f2: .float 9.0
.globl main
.type main, #function
main:
flds f1
flds f2
fcomip
fstp %st(0) # to clear stack
ja leb # won't jump, jbe will
pushl $msg
call printf
addl $4, %esp
leb:
pushl $0
call exit

Setting text and background in Assembly intel

I have a programming assignment to run through and set the background and text of all the possible combinations. I am using a predefined function called SetTextColor which basically sets the values like this:
mov eax, white + (blue * 16)
Essentially this sets the text white and the background blue (to set the background you multiply by 16). Basically the combination is 16 X 16 = 256
TITLE BACKGROUND COLORS (main.asm)
; Description: T
; Author: Chad Peppers
; Revision date: June 21, 2012
INCLUDE Irvine32.inc
.data
COUNT = 16
COUNT2 = 16
LCOUNT DWORD ?
val1 DWORD 0
val2 DWORD 0
.code
main PROC
mov ecx, COUNT
L1:
mov LCOUNT, ecx
mov ecx, COUNT2
L2:
mov eax, val1 + (val2 * 16)
call SetTextColor
inc val2
Loop L2
mov ecx, LCOUNT
Loop L1
call DumpRegs
exit
main ENDP
END main
Basically I am doing a nested loop. My thinking is that I simply do a 1 * (1 * 16) then inc the value in a nested loop until 1 * (16 * 16). I am getting the error below
I am getting the error A2026: constant expected
I imagine the error you are getting is at this line:
mov eax, val1 + (val2 * 16)
You just can't do that. If you intend to multiply val2 by 16 and then add val1 to the result, then you need to implement it step by step (you may come across addressing in the form of a+b*c but a and c need to be registers and b can only be 2, 4 or 8, not 16). Try replacing this line with something like this:
mov eax, val2
imul eax, 16
add aex, val1

MIPS - help converting code from C

I am a beginner in MIPS and I am trying to write a simple code that runs over a given array in memory that is smaller than 10 cells, lets say 9 cells, and prints on screen the biggest number.
I wrote a C code that solves this issue, but I don't know how to convert it (without mips gcc) to a working MIPS assembly code.
The code I wrote:
int N = 9 , i = 0 , biggest = 0 ;
int arr [N] = -2 , 3 , 9 , -1 , 5 , 6 , 10 , 52 , 9 ;
while ( i <= N )
{
if ( arr [i] > biggest )
biggest = arr [i] ;
i++ ;
}
printf ( "biggest number is: %d" , biggest ) ;
I will be more than happy if someone can write that code in MIPS assembly, and explain it to me.
Thank you !
Just focusing on the loop, try something like that:
.text
.set noreorder
.global get_max
get_max:
li $4, array // start pointer
li $5, array_end-array-4 // end pointer
li $2, 0 // 'biggest' as result
lw $6, 0($4) // load first table entry
1: slt $3, $2, $6 // boolean flag (biggest<arr[i])
movn $2, $6, $3 // update 'biggest' when flag is set
lw $6, 4($4) // load next table entry
bne $4, $5, 1b // continue until we hit end of array
addiu $4, 4 // advance to next cell (using bne delay slot)
jr $31 // return to the caller
nop // safely fill the delay slot
.data
array: .long -2 , 3 , 9 , -1 , 5 , 6 , 10 , 52 , 9
array_end: .long 0
Compile this into a separate assembly source file and link with your main C code.
Don't forget to call the function from your C code:
printf("biggest=%d\n",get_max());
You have a problem with your initialization...

SSE best way to set register to 0.0's and 1.0's?

I am doing some sse vector3 math.
Generally, I set the 4th digit of my vector to 1.0f, as this makes most of my math work, but sometimes I need to set it to 0.0f.
So I want to change something like:
(32.4f, 21.2f, -4.0f, 1.0f) to (32.4f, 21.2f, -4.0f, 0.0f)
I was wondering what the best method to doing so would be:
Convert to 4 floats, set 4th float, send back to SSE
xor a register with itself, then do 2 shufps
Do all the SSE math with 1.0f and then set the variables to what they should be when finished.
Other?
Note: The vector is already in a SSE register when I need to change it.
AND with a constant mask.
In assembly ...
myMask:
.long 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000
...
andps myMask, %xmm#
where # = {0, 1, 2, ....}
Hope this helps.
Assuming your original vector is in xmm0:
; xmm0 = [x y z w]
xorps %xmm1, %xmm1 ; [0 0 0 0]
pcmpeqs %xmm2, %xmm2 ; [1 1 1 1]
movss %xmm1, %xmm2 ; [0 1 1 1]
pshufd $0x20, %xmm1, %xmm2 ; [1 1 1 0]
andps %xmm2, %xmm0 ; [x y z 0]
should be fast since it does not access memory.
If you want to do it without memory access, you could realize that the value 1 has a zero word in it, and the value zero is all zeroes. So, you can just copy the zero word to the other. If you have the 1 in the highest dword, pshufhw xmm0, xmm0, 0xa4 should do the trick:
(gdb) ni
4 pshufhw $0xa4, %xmm0, %xmm0
(gdb) p $xmm0.v4_float
$4 = {32.4000015, 21.2000008, -4, 1}
(gdb) ni
5 ret
(gdb) p $xmm0.v4_float
$5 = {32.4000015, 21.2000008, -4, 0}
The similar trick for the other locations is left as an excercise to the reader :)
pinsrw?
Why not multiply your vector element wise with [1 1 1 0]? I'm pretty sure there is an SSE instruction for element wise multiplication.
Then to go back to a vector with a 1 in the 4th dimension, just add [0 0 0 1]. Again there is an SSE instruction for that, too.

Resources