2

I am currently creating a program to convert an decimal into binary. I am currently using the shifting method in order to get the 0's and 1's.

I have looked at other threads which leads to using LAHF and PUSHF to access the flags and set it; however, all I want to do is get the current value of the carry flag and store it into a register (i.e: 1's or 0's at that current position) which will later be copied into the array. Since I am not too familiar with LAFH or PUSHF, I was wondering if you can complete the same task I asked above using LAFH or PUSHF.

For example, I want to move the current CF into eax: mov edx,cf (I know this doesn't work, but I am looking for something like this). After I have copied either the 1 or 0, I will then move it into the array which was passed from a C++ program.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Andrew Nguyen
  • 115
  • 3
  • 10

4 Answers4

4

Almost identical to this question: check if carry flag is set

You could uses JC, JNC to branch based on carry flag then mov 1 or 0 into the register you want to use.

Or use ADC command.

mov eax, 0
adc eax, 0

I will add that PUSHF then pop into the register and mask out the bit you want with an XOR would also work. The ADC approach is probably best

Community
  • 1
  • 1
guest
  • 41
  • 1
3

I find the most obvious way to store the carry in EDX is:

setc  dl
movzx edx, dl

It is shorter (6 bytes) than the methods proposed in the other answers but the shortest (5 bytes) has to be:

pushfd
pop   edx
and   edx, 1
Fifoernik
  • 9,779
  • 1
  • 21
  • 27
  • 4
    shorter: `xor edx,edx / ` generate flags `/ setc dl`. 5 bytes with good performance (choice of `xor` before or `movzx` after [depends on microarchitecture](http://agner.org/optimize/). Shortest: `sbb edx, edx` 2 bytes, also quite good performance. Or `sbb edx, edx / neg edx` 4 bytes, if you really need 0/1 rather than 0/-1. `sbb reg,reg` is actually used by gcc in some cases. (seen in the disassembly of `/bin/ls` for example.) I'm out of votes or I'd def upvote this. The other answers are mostly insane. – Peter Cordes Nov 19 '15 at 11:53
  • 2
    @AndrewNguyen: you should change your accept to this answer. It's better. – Peter Cordes Nov 19 '15 at 11:56
  • @PeterCordes Your first example __looses__ the carry flag through `XOR` – Fifoernik Nov 19 '15 at 11:56
  • Oh right. Of course you have to put the xor before the flag-generating instructions, I should have said that. Fixed inside the edit window :) – Peter Cordes Nov 19 '15 at 11:57
1

Just do a conditional assignment based on carry:

mov eax, 1
jc carry_set ; If carry is indeed set, skip the next line
mov eax, 0
carry_set:

In general, carry is typically used for conditional jumps, not as a value. See if the larger code can be reformulated this way.

EDIT: modern Intel CPUs also have a conditional move command:

mov eax, 0
cmovc eax, 1 ; assign if carry is set
Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • Thank you for the response! If only I can select two answers! Both of these seems to work fine as I just tested both and ended with the same results. – Andrew Nguyen Nov 18 '15 at 19:20
  • 2
    `setc al / movzx eax, al` would be *much* better than either of those. `setcc` has existed since 386. – Peter Cordes Nov 19 '15 at 11:39
1

You can always try subtract with borrow. For example ...

SBB EAX, EAX

If the carry flag is set, EAX will be 0xFFFFFFFF. If it is clear, the result will be 0x00000000.

Sparky
  • 13,505
  • 4
  • 26
  • 27