It can simulate all the basic 8085 instructions, along with the Hardware and Software Interrupts. Inbuilt IDE and Assembler can be used to write and assemble 8085 ASM program and also load it directly to 8085 memory or even save it to HEX file. The program requires Microsoft.NET Framework 2.0 to execute and is compatible with all Windows. Explore executables by dissecting its sections, strings, symbols, raw hex and machine level instructions. Machine Architecture ODA supports over 60 machine architectures, including x86, ARM, PowerPC, MIPS, and many more.
Technical Support
Support Resources
- Support Knowledgebase
Product Information
- Software & Hardware Products
Information in this article applies to:
- Keil MDK All Versions
- C166 All Versions
- C251 All Versions
- C51 All Versions
QUESTION
What is the Intel HEX file format?
ANSWER
The Intel HEX file is an ASCII text file with lines of text that follow the Intel HEX file format. Each line in an Intel HEX file contains one HEX record. These records are made up of hexadecimal numbers that represent machine language code and/or constant data. Intel HEX files are often used to transfer the program and data that would be stored in a ROM or EPROM. Most EPROM programmers or emulators can use Intel HEX files.
Record Format
An Intel HEX file is composed of any number of HEX records. Each record is made up of five fields that are arranged in the following format:
Each group of letters corresponds to a different field, and each letter represents a single hexadecimal digit. Each field is composed of at least two hexadecimal digits-which make up a byte-as described below:
- : is the colon that starts every Intel HEX record.
- ll is the record-length field that represents the number of data bytes (dd) in the record.
- aaaa is the address field that represents the starting address for subsequent data in the record.
- tt is the field that represents the HEX record type, which may be one of the following:
00 - data record
01 - end-of-file record
02 - extended segment address record
04 - extended linear address record
05 - start linear address record (MDK-ARM only) - dd is a data field that represents one byte of data. A record may have multiple data bytes. The number of data bytes in the record must match the number specified by the ll field.
- cc is the checksum field that represents the checksum of the record. The checksum is calculated by summing the values of all hexadecimal digit pairs in the record modulo 256 and taking the two's complement.
Data Records
The Intel HEX file is made up of any number of data records that are terminated with a carriage return and a linefeed. Data records appear as follows:
This record is decoded as follows:
where:
- 10 is the number of data bytes in the record.
- 2462 is the address where the data are to be located in memory.
- 00 is the record type 00 (a data record).
- 464C..464C is the data.
- 33 is the checksum of the record.
Extended Linear Address Records (HEX386)
Extended linear address records are also known as 32-bit address records and HEX386 records. These records contain the upper 16 bits (bits 16-31) of the data address. The extended linear address record always has two data bytes and appears as follows:
where:
Arm Asm To Hex Converter Software Windows 10
- 02 is the number of data bytes in the record.
- 0000 is the address field. For the extended linear address record, this field is always 0000.
- 04 is the record type 04 (an extended linear address record).
- FFFF is the upper 16 bits of the address.
- FC is the checksum of the record and is calculated as
01h + NOT(02h + 00h + 00h + 04h + FFh + FFh).
When an extended linear address record is read, the extended linear address stored in the data field is saved and is applied to subsequent records read from the Intel HEX file. The linear address remains effective until changed by another extended address record.
The absolute-memory address of a data record is obtained by adding the address field in the record to the shifted address data from the extended linear address record. The following example illustrates this process.
Extended Segment Address Records (HEX86)
Extended segment address records-also known as HEX86 records-contain bits 4-19 of the data address segment. The extended segment address record always has two data bytes and appears as follows:
where:
- 02 is the number of data bytes in the record.
- 0000 is the address field. For the extended segment address record, this field is always 0000.
- 02 is the record type 02 (an extended segment address record).
- 1200 is the segment of the address.
- EA is the checksum of the record and is calculated as
01h + NOT(02h + 00h + 00h + 02h + 12h + 00h).
When an extended segment address record is read, the extended segment address stored in the data field is saved and is applied to subsequent records read from the Intel HEX file. The segment address remains effective until changed by another extended address record.
The absolute-memory address of a data record is obtained by adding the address field in the record to the shifted-address data from the extended segment address record. The following example illustrates this process.
Start Linear Address Records (MDK-ARM only)
Start linear address records specify the start address of the application. These records contain the full linear 32 bit address. The start linear address record always has four data bytes and appears as follows:
where:
- 04 is the number of data bytes in the record.
- 0000 is the address field. For the start linear address record, this field is always 0000.
- 05 is the record type 05 (a start linear address record).
- 000000CD is the 4 byte linear start address of the application.
- 2A is the checksum of the record and is calculated as
01h + NOT(04h + 00h + 00h + 05h + 00h + 00h + 00h + CDh).
The Start Linear Address specifies the address of the __main (pre-main) function but not the address of the startup code which usually calls __main after calling SystemInit(). An odd linear start address specifies that __main is compiled for the Thumb instruction set.
The Start Linear Address Record can appear anywhere in hex file. In most cases this record can be ignored because it does not contain information which is needed to program flash memory.
End-of-File (EOF) Records
Asm To Hex Converter Software
An Intel HEX file must end with an end-of-file (EOF) record. This record must have the value 01 in the record type field. An EOF record always appears as follows:
where:
- 00 is the number of data bytes in the record.
- 0000 is the address where the data are to be located in memory. The address in end-of-file records is meaningless and is ignored. An address of 0000h is typical.
- 01 is the record type 01 (an end-of-file record).
- FF is the checksum of the record and is calculated as
01h + NOT(00h + 00h + 00h + 01h).
Example Intel HEX File
Following is an example of a complete Intel HEX file:
SEE ALSO
SEE ALSO FOR 8051
- Refer to the OH51 User's Guide.
- Refer to the OHX51 User's Guide.
Last Reviewed: Thursday, February 25, 2021
ProductsDevelopment Tools | Hardware & Collateral | Downloads | Support | Contact |
Cookie Settings | Terms of Use | Privacy | Accessibility | Trademarks | Contact Us | Feedback Copyright © 2005-2019 Arm Limited (or its affiliates). All rights reserved. |
Next: Constraints, Previous: Basic Asm, Up: Using Assembly Language with C [Contents][Index]
6.47.2 Extended Asm - Assembler Instructions with C Expression Operands
With extended asm
you can read and write C variables from assembler and perform jumps from assembler code to C labels. Extended asm
syntax uses colons (‘:’) to delimitthe operand parameters after the assembler template:
where in the last form, asm-qualifiers contains goto
(and in thefirst form, not).
The asm
keyword is a GNU extension.When writing code that can be compiled with -ansi and thevarious -std options, use __asm__
instead of asm
(see Alternate Keywords).
Qualifiers
volatile
The typical use of extended asm
statements is to manipulate input values to produce output values. However, your asm
statements may also produce side effects. If so, you may need to use the volatile
qualifier to disable certain optimizations. See Volatile.
inline
If you use the inline
qualifier, then for inlining purposes the sizeof the asm
statement is taken as the smallest size possible(see Size of an asm).
goto
This qualifier informs the compiler that the asm
statement may perform a jump to one of the labels listed in the GotoLabels.See GotoLabels.
Parameters
This is a literal string that is the template for the assembler code. It is a combination of fixed text and tokens that refer to the input, output, and goto parameters. See AssemblerTemplate.
A comma-separated list of the C variables modified by the instructions in the AssemblerTemplate. An empty list is permitted. See OutputOperands.
A comma-separated list of C expressions read by the instructions in the AssemblerTemplate. An empty list is permitted. See InputOperands.
A comma-separated list of registers or other values changed by the AssemblerTemplate, beyond those listed as outputs.An empty list is permitted. See Clobbers and Scratch Registers.
When you are using the goto
form of asm
, this section contains the list of all C labels to which the code in the AssemblerTemplate may jump. See GotoLabels.
asm
statements may not perform jumps into other asm
statements,only to the listed GotoLabels.GCC’s optimizers do not know about other jumps; therefore they cannot take account of them when deciding how to optimize.
The total number of input + output + goto operands is limited to 30.
Remarks
The asm
statement allows you to include assembly instructions directly within C code. This may help you to maximize performance in time-sensitive code or to access assembly instructions that are not readily available to C programs.
Note that extended asm
statements must be inside a function. Only basic asm
may be outside functions (see Basic Asm).Functions declared with the naked
attribute also require basic asm
(see Function Attributes).
While the uses of asm
are many and varied, it may help to think of an asm
statement as a series of low-level instructions that convert input parameters to output parameters. So a simple (if not particularly useful) example for i386 using asm
might look like this:
This code copies src
to dst
and add 1 to dst
.
6.47.2.1 Volatile
GCC’s optimizers sometimes discard asm
statements if they determine there is no need for the output variables. Also, the optimizers may move code out of loops if they believe that the code will always return the same result (i.e. none of its input values change between calls). Using the volatile
qualifier disables these optimizations. asm
statements that have no output operands and asm goto
statements, are implicitly volatile.
This i386 code demonstrates a case that does not use (or require) the volatile
qualifier. If it is performing assertion checking, this code uses asm
to perform the validation. Otherwise, dwRes
is unreferenced by any code. As a result, the optimizers can discard the asm
statement, which in turn removes the need for the entire DoCheck
routine. Forex killer 4 12 keygen. By omitting the volatile
qualifier when it isn’t needed you allow the optimizers to produce the most efficient code possible.
The next example shows a case where the optimizers can recognize that the input (dwSomeValue
) never changes during the execution of the function and can therefore move the asm
outside the loop to produce more efficient code. Again, using the volatile
qualifier disables this type of optimization.
The following example demonstrates a case where you need to use the volatile
qualifier. It uses the x86 rdtsc
instruction, which reads the computer’s time-stamp counter. Without the volatile
qualifier, the optimizers might assume that the asm
block will always return the same value and therefore optimize away the second call.
GCC’s optimizers do not treat this code like the non-volatile code in the earlier examples. They do not move it out of loops or omit it on the assumption that the result from a previous call is still valid.
Note that the compiler can move even volatile asm
instructions relativeto other code, including across jump instructions. For example, on many targets there is a system register that controls the rounding mode of floating-point operations. Setting it with a volatile asm
statement,as in the following PowerPC example, does not work reliably.
The compiler may move the addition back before the volatile asm
statement. To make it work as expected, add an artificial dependency tothe asm
by referencing a variable in the subsequent code, forexample:
Under certain circumstances, GCC may duplicate (or remove duplicates of) your assembly code when optimizing. This can lead to unexpected duplicate symbol errors during compilation if your asm
code defines symbols or labels. Using ‘%=’ (see AssemblerTemplate) may help resolve this problem.
6.47.2.2 Assembler Template
An assembler template is a literal string containing assembler instructions.The compiler replaces tokens in the template that refer to inputs, outputs, and goto labels,and then outputs the resulting string to the assembler. The string can contain any instructions recognized by the assembler, including directives. GCC does not parse the assembler instructions themselves and does not know what they mean or even whether they are valid assembler input. However, it does count the statements (see Size of an asm).
You may place multiple assembler instructions together in a single asm
string, separated by the characters normally used in assembly code for the system. A combination that works in most places is a newline to break the line, plus a tab character to move to the instruction field (written as ‘nt’). Some assemblers allow semicolons as a line separator. However, note that some assembler dialects use semicolons to start a comment.
Do not expect a sequence of asm
statements to remain perfectly consecutive after compilation, even when you are using the volatile
qualifier. If certain instructions need to remain consecutive in the output, put them in a single multi-instruction asm
statement.
Accessing data from C programs without using input/output operands (such as by using global symbols directly from the assembler template) may not work as expected. Similarly, calling functions directly from an assembler template requires a detailed understanding of the target assembler and ABI.
Since GCC does not parse the assembler template,it has no visibility of any symbols it references. This may result in GCC discarding those symbols as unreferenced unless they are also listed as input, output, or goto operands.
Special format strings
In addition to the tokens described by the input, output, and goto operands, these tokens have special meanings in the assembler template:
Outputs a single ‘%’ into the assembler code.
Outputs a number that is unique to each instance of the asm
statement in the entire compilation. This option is useful when creating local labels and referring to them multiple times in a single template that generates multiple assembler instructions.
Outputs ‘{’, ‘|’, and ‘}’ characters (respectively)into the assembler code. When unescaped, these characters have specialmeaning to indicate multiple assembler dialects, as described below.
Multiple assembler dialects in asm
templates
On targets such as x86, GCC supports multiple assembler dialects.The -masm option controls which dialect GCC uses as its default for inline assembler. The target-specific documentation for the -masm option contains the list of supported dialects, as well as the default dialect if the option is not specified. This information may be important to understand, since assembler code that works correctly when compiled using one dialect will likely fail if compiled using another.See x86 Options.
If your code needs to support multiple assembler dialects (for example, if you are writing public headers that need to support a variety of compilation options), use constructs of this form:
This construct outputs dialect0
when using dialect #0 to compile the code, dialect1
for dialect #1, etc. If there are fewer alternatives within the braces than the number of dialects the compiler supports, the construct outputs nothing.
For example, if an x86 compiler supports two dialects(‘att’, ‘intel’), an assembler template such as this:
is equivalent to one of
Using that same compiler, this code:
corresponds to either
There is no support for nesting dialect alternatives.
6.47.2.3 Output Operands
An asm
statement has zero or more output operands indicating the namesof C variables modified by the assembler code.
In this i386 example, old
(referred to in the template string as %0
) and *Base
(as %1
) are outputs and Offset
(%2
) is an input:
Operands are separated by commas. Each operand has this format:
Specifies a symbolic name for the operand.Reference the name in the assembler template by enclosing it in square brackets (i.e. ‘%[Value]’). The scope of the name is the asm
statement that contains the definition. Any valid C variable name is acceptable, including names already defined in the surrounding code. No two operands within the same asm
statement can use the same symbolic name.
When not using an asmSymbolicName, use the (zero-based) positionof the operand in the list of operands in the assembler template. For example if there are three output operands, use ‘%0’ in the template to refer to the first, ‘%1’ for the second, and ‘%2’ for the third.
A string constant specifying constraints on the placement of the operand; See Constraints, for details.
Output constraints must begin with either ‘=’ (a variable overwriting an existing value) or ‘+’ (when reading and writing). When using ‘=’, do not assume the location contains the existing valueon entry to the asm
, except when the operand is tied to an input; see Input Operands.
After the prefix, there must be one or more additional constraints (see Constraints) that describe where the value resides. Common constraints include ‘r’ for register and ‘m’ for memory. When you list more than one possible location (for example, '=rm'
),the compiler chooses the most efficient one based on the current context. If you list as many alternates as the asm
statement allows, you permit the optimizers to produce the best possible code. If you must use a specific register, but your Machine Constraints do notprovide sufficient control to select the specific register you want, local register variables may provide a solution (see Local Register Variables).
Specifies a C lvalue expression to hold the output, typically a variable name.The enclosing parentheses are a required part of the syntax.
When the compiler selects the registers to use to represent the output operands, it does not use any of the clobbered registers (see Clobbers and Scratch Registers).
Output operand expressions must be lvalues. The compiler cannot check whether the operands have data types that are reasonable for the instruction being executed. For output expressions that are not directly addressable (for example a bit-field), the constraint must allow a register. In that case, GCC uses the register as the output of the asm
, and then stores that register into the output.
Operands using the ‘+’ constraint modifier count as two operands (that is, both as input and output) towards the total maximum of 30 operandsper asm
statement.
Use the ‘&’ constraint modifier (see Modifiers) on all outputoperands that must not overlap an input. Otherwise, GCC may allocate the output operand in the same register as an unrelated input operand, on the assumption that the assembler code consumes its inputs before producing outputs. This assumption may be false if the assembler code actually consists of more than one instruction.
The same problem can occur if one output parameter (a) allows a register constraint and another output parameter (b) allows a memory constraint.The code generated by GCC to access the memory address in b can containregisters which might be shared by a, and GCC considers those registers to be inputs to the asm. As above, GCC assumes that such inputregisters are consumed before any outputs are written. This assumption may result in incorrect behavior if the asm
statement writes to abefore usingb. Combining the ‘&’ modifier with the register constraint on aensures that modifying a does not affect the address referenced by b. Otherwise, the location of b is undefined if a is modified before using b.
asm
supports operand modifiers on operands (for example ‘%k2’ instead of simply ‘%2’). Typically these qualifiers are hardware dependent. The list of supported modifiers for x86 is found at x86 Operand modifiers.
If the C code that follows the asm
makes no use of any of the output operands, use volatile
for the asm
statement to prevent the optimizers from discarding the asm
statement as unneeded (see Volatile).
This code makes no use of the optional asmSymbolicName. Therefore it references the first output operand as %0
(were there a second, it would be %1
, etc). The number of the first input operand is one greater than that of the last output operand. In this i386 example, that makes Mask
referenced as %1
:
That code overwrites the variable Index
(‘=’),placing the value in a register (‘r’).Using the generic ‘r’ constraint instead of a constraint for a specific register allows the compiler to pick the register to use, which can result in more efficient code. This may not be possible if an assembler instruction requires a specific register.
The following i386 example uses the asmSymbolicName syntax.It produces the same result as the code above, but some may consider it more readable or more maintainable since reordering index numbers is not necessary when adding or removing operands. The names aIndex
and aMask
are only used in this example to emphasize which names get used where.It is acceptable to reuse the names Index
and Mask
.
Here are some more examples of output operands.
Here, d
may either be in a register or in memory. Since the compiler might already have the current value of the uint32_t
locationpointed to by e
in a register, you can enable it to choose the best locationfor d
by specifying both constraints.
6.47.2.4 Flag Output Operands
Some targets have a special register that holds the “flags” for theresult of an operation or comparison. Normally, the contents of thatregister are either unmodifed by the asm, or the asm
statement isconsidered to clobber the contents.
On some targets, a special form of output operand exists by whichconditions in the flags register may be outputs of the asm. The set ofconditions supported are target specific, but the general rule is thatthe output variable must be a scalar integer, and the value is boolean.When supported, the target defines the preprocessor symbol__GCC_ASM_FLAG_OUTPUTS__
.
Because of the special nature of the flag output operands, the constraintmay not include alternatives.
Most often, the target has only one flags register, and thus is an impliedoperand of many instructions. In this case, the operand should not bereferenced within the assembler template via %0
etc, as there’sno corresponding text in the assembly language.
The flag output constraints for the ARM family are of the form‘=@cccond’ where cond is one of the standardconditions defined in the ARM ARM for ConditionHolds
.
eq
Z flag set, or equal
ne
Z flag clear or not equal
cs
hs
C flag set or unsigned greater than equal
cc
lo
C flag clear or unsigned less than
mi
N flag set or “minus”
pl
N flag clear or “plus”
vs
V flag set or signed overflow
vc
V flag clear
hi
unsigned greater than
ls
unsigned less than equal
ge
signed greater than equal
lt
signed less than
gt
signed greater than
le
signed less than equal
The flag output constraints are not supported in thumb1 mode.
The flag output constraints for the x86 family are of the form‘=@cccond’ where cond is one of the standardconditions defined in the ISA manual for jcc
orsetcc
.
a
“above” or unsigned greater than
ae
“above or equal” or unsigned greater than or equal
b
“below” or unsigned less than
be
“below or equal” or unsigned less than or equal
c
carry flag set
e
z
“equal” or zero flag set
g
signed greater than
ge
signed greater than or equal
l
signed less than
le
signed less than or equal
o
overflow flag set
p
parity flag set
s
sign flag set
na
nae
nb
nbe
nc
ne
ng
nge
nl
nle
no
np
ns
nz
“not” flag, or inverted versions of those above
6.47.2.5 Input Operands
Input operands make values from C variables and expressions available to the assembly code.
Operands are separated by commas. Each operand has this format:
Specifies a symbolic name for the operand.Reference the name in the assembler template by enclosing it in square brackets (i.e. ‘%[Value]’). The scope of the name is the asm
statement that contains the definition. Any valid C variable name is acceptable, including names already defined in the surrounding code. No two operands within the same asm
statement can use the same symbolic name.
When not using an asmSymbolicName, use the (zero-based) positionof the operand in the list of operands in the assembler template. For example if there aretwo output operands and three inputs,use ‘%2’ in the template to refer to the first input operand,‘%3’ for the second, and ‘%4’ for the third.
A string constant specifying constraints on the placement of the operand; See Constraints, for details.
Input constraint strings may not begin with either ‘=’ or ‘+’.When you list more than one possible location (for example, ‘'irm'’), the compiler chooses the most efficient one based on the current context.If you must use a specific register, but your Machine Constraints do notprovide sufficient control to select the specific register you want, local register variables may provide a solution (see Local Register Variables).
Input constraints can also be digits (for example, '0'
). This indicates that the specified input must be in the same place as the output constraint at the (zero-based) index in the output constraint list. When using asmSymbolicName syntax for the output operands,you may use these names (enclosed in brackets ‘[]’) instead of digits.
This is the C variable or expression being passed to the asm
statement as input. The enclosing parentheses are a required part of the syntax.
When the compiler selects the registers to use to represent the input operands, it does not use any of the clobbered registers(see Clobbers and Scratch Registers).
If there are no output operands but there are input operands, place two consecutive colons where the output operands would go:
Warning: Do not modify the contents of input-only operands (except for inputs tied to outputs). The compiler assumes that on exit from the asm
statement these operands contain the same values as they had before executing the statement. It is not possible to use clobbersto inform the compiler that the values in these inputs are changing. One common work-around is to tie the changing input variable to an output variable that never gets used. Note, however, that if the code that follows the asm
statement makes no use of any of the output operands, the GCC optimizers may discard the asm
statement as unneeded (see Volatile).
asm
supports operand modifiers on operands (for example ‘%k2’ instead of simply ‘%2’). Typically these qualifiers are hardware dependent. The list of supported modifiers for x86 is found at x86 Operand modifiers.
In this example using the fictitious combine
instruction, the constraint '0'
for input operand 1 says that it must occupy the same location as output operand 0. Only input operands may use numbers in constraints, and they must each refer to an output operand. Only a number (or the symbolic assembler name) in the constraint can guarantee that one operand is in the same place as another. The mere fact that foo
is the value of both operands is not enough to guarantee that they are in the same place in the generated assembler code.
Here is an example using symbolic names.
6.47.2.6 Clobbers and Scratch Registers
While the compiler is aware of changes to entries listed in the output operands, the inline asm
code may modify more than just the outputs. For example, calculations may require additional registers, or the processor may overwrite a register as a side effect of a particular assembler instruction. In order to inform the compiler of these changes, list them in the clobber list. Clobber list items are either register names or the special clobbers (listed below). Each clobber list item is a string constant enclosed in double quotes and separated by commas.
Clobber descriptions may not in any way overlap with an input or output operand. For example, you may not have an operand describing a register class with one member when listing that register in the clobber list. Variables declared to live in specific registers (see Explicit Register Variables) and used as asm
input or output operands must have no part mentioned in the clobber description. In particular, there is no way to specify that input operands get modified without also specifying them as output operands.
When the compiler selects which registers to use to represent input and output operands, it does not use any of the clobbered registers. As a result, clobbered registers are available for any use in the assembler code.
Another restriction is that the clobber list should not contain thestack pointer register. This is because the compiler requires thevalue of the stack pointer to be the same after an asm
statement as it was on entry to the statement. However, previousversions of GCC did not enforce this rule and allowed the stackpointer to appear in the list, with unclear semantics. This behavioris deprecated and listing the stack pointer may become an error infuture versions of GCC.
Here is a realistic example for the VAX showing the use of clobbered registers:
Also, there are two special clobber arguments:
'cc'
The 'cc'
clobber indicates that the assembler code modifies the flags register. On some machines, GCC represents the condition codes as a specific hardware register; 'cc'
serves to name this register.On other machines, condition code handling is different, and specifying 'cc'
has no effect. But it is valid no matter what the target.
'memory'
The 'memory'
clobber tells the compiler that the assembly codeperforms memory reads or writes to items other than those listed in the input and output operands (for example, accessing the memory pointed to by one of the input parameters). To ensure memory contains correct values, GCC may need to flush specific register values to memory before executing the asm
. Further, the compiler does not assume that any values read from memory before an asm
remain unchanged after that asm
; it reloads them as needed. Using the 'memory'
clobber effectively forms a read/writememory barrier for the compiler.
Note that this clobber does not prevent the processor from doing speculative reads past the asm
statement. To prevent that, you need processor-specific fence instructions.
Flushing registers to memory has performance implications and may bean issue for time-sensitive code. You can provide better informationto GCC to avoid this, as shown in the following examples. At aminimum, aliasing rules allow GCC to know what memory doesn’tneed to be flushed.
Here is a fictitious sum of squares instruction, that takes twopointers to floating point values in memory and produces a floatingpoint register output.Notice that x
, and y
both appear twice in the asm
parameters, once to specify memory accessed, and once to specify abase register used by the asm
. You won’t normally be wasting aregister by doing this as GCC can use the same register for bothpurposes. However, it would be foolish to use both %1
and%3
for x
in this asm
and expect them to be thesame. In fact, %3
may well not be a register. It might be asymbolic memory reference to the object pointed to by x
.
Here is a fictitious *z++ = *x++ * *y++
instruction.Notice that the x
, y
and z
pointer registersmust be specified as input/output because the asm
modifiesthem.
An x86 example where the string memory argument is of unknown length.
If you know the above will only be reading a ten byte array then youcould instead use a memory input like:'m' (*(const char (*)[10]) p)
.
Here is an example of a PowerPC vector scale implemented in assembly,complete with vector and condition code clobbers, and some initializedoffset registers that are unchanged by the asm
.
Rather than allocating fixed registers via clobbers to provide scratchregisters for an asm
statement, an alternative is to define avariable and make it an early-clobber output as with a2
anda3
in the example below. This gives the compiler registerallocator more freedom. You can also define a variable and make it anoutput tied to an input as with a0
and a1
, tiedrespectively to ap
and lda
. Of course, with tiedoutputs your asm
can’t use the input value after modifying theoutput register since they are one and the same register. What’smore, if you omit the early-clobber on the output, it is possible thatGCC might allocate the same register to another of the inputs if GCCcould prove they had the same value on entry to the asm
. Thisis why a1
has an early-clobber. Its tied input, lda
might conceivably be known to have the value 16 and without anearly-clobber share the same register as %11
. On the otherhand, ap
can’t be the same as any of the other inputs, so anearly-clobber on a0
is not needed. It is also not desirable inthis case. An early-clobber on a0
would cause GCC to allocatea separate register for the 'm' (*(const double (*)[]) ap)
input. Note that tying an input to an output is the way to set up aninitialized temporary register modified by an asm
statement.An input not tied to an output is assumed by GCC to be unchanged, forexample 'b' (16)
below sets up %11
to 16, and GCC mightuse that register in following code if the value 16 happened to beneeded. You can even use a normal asm
output for a scratch ifall inputs that might share the same register are consumed before thescratch is used. The VSX registers clobbered by the asm
statement could have used this technique except for GCC’s limit on thenumber of asm
parameters.
6.47.2.7 Goto Labels
asm goto
allows assembly code to jump to one or more C labels. TheGotoLabels section in an asm goto
statement contains a comma-separated list of all C labels to which the assembler code may jump. GCC assumes that asm
execution falls through to the next statement (if this is not the case, consider using the __builtin_unreachable
intrinsic after the asm
statement). Optimization of asm goto
may be improved by using the hot
and cold
label attributes (see Label Attributes).
If the assembler code does modify anything, use the 'memory'
clobber to force the optimizers to flush all register values to memory and reload them if necessary after the asm
statement.
Also note that an asm goto
statement is always implicitlyconsidered volatile.
Be careful when you set output operands inside asm goto
only onsome possible control flow paths. If you don’t set up the output ongiven path and never use it on this path, it is okay. Otherwise, youshould use ‘+’ constraint modifier meaning that the operand isinput and output one. With this modifier you will have the correctvalues on all possible paths from the asm goto
.
To reference a label in the assembler template, prefix it with‘%l’ (lowercase ‘L’) followed by its (zero-based) positionin GotoLabels plus the number of input and output operands.Output operand with constraint modifier ‘+’ is counted as twooperands because it is considered as one output and one input operand.For example, if the asm
has three inputs, one output operandwith constraint modifier ‘+’ and one output operand withconstraint modifier ‘=’ and references two labels, refer to thefirst label as ‘%l6’ and the second as ‘%l7’). Service tool v 4905 free download.
Alternately, you can reference labels using the actual C label nameenclosed in brackets. For example, to reference a label namedcarry
, you can use ‘%l[carry]’. The label must still belisted in the GotoLabels section when using this approach. Itis better to use the named references for labels as in this case youcan avoid counting input and output operands and special treatment ofoutput operands with constraint modifier ‘+’.
Here is an example of asm goto
for i386:
The following example shows an asm goto
that uses a memory clobber.
The following example shows an asm goto
that uses an output.
The following artificial example shows an asm goto
that setsup an output only on one path inside the asm goto
. Usage ofconstraint modifier =
instead of +
would be wrong asfactor
is used on all paths from the asm goto
.
6.47.2.8 x86 Operand Modifiers
References to input, output, and goto operands in the assembler templateof extended asm
statements can use modifiers to affect the way the operands are formatted in the code output to the assembler. For example, the following code uses the ‘h’ and ‘b’ modifiers for x86:
These modifiers generate this assembler code:
The rest of this discussion uses the following code for illustrative purposes.
With no modifiers, this is what the output from the operands would befor the ‘att’ and ‘intel’ dialects of assembler:
Operand | ‘att’ | ‘intel’ |
---|---|---|
%0 | %eax | eax |
%1 | $2 | 2 |
%3 | $.L3 | OFFSET FLAT:.L3 |
%4 | $8 | 8 |
%5 | %xmm0 | xmm0 |
%7 | $0 | 0 |
The table below shows the list of supported modifiers and their effects.
Modifier | Description | Operand | ‘att’ | ‘intel’ |
---|---|---|---|---|
A | Print an absolute memory reference. | %A0 | *%rax | rax |
b | Print the QImode name of the register. | %b0 | %al | al |
B | print the opcode suffix of b. | %B0 | b | |
c | Require a constant operand and print the constant expression with no punctuation. | %c1 | 2 | 2 |
d | print duplicated register operand for AVX instruction. | %d5 | %xmm0, %xmm0 | xmm0, xmm0 |
E | Print the address in Double Integer (DImode) mode (8 bytes) when the target is 64-bit.Otherwise mode is unspecified (VOIDmode). | %E1 | %(rax) | [rax] |
g | Print the V16SFmode name of the register. | %g0 | %zmm0 | zmm0 |
h | Print the QImode name for a “high” register. | %h0 | %ah | ah |
H | Add 8 bytes to an offsettable memory reference. Useful when accessing thehigh 8 bytes of SSE values. For a memref in (%rax), it generates | %H0 | 8(%rax) | 8[rax] |
k | Print the SImode name of the register. | %k0 | %eax | eax |
l | Print the label name with no punctuation. | %l3 | .L3 | .L3 |
L | print the opcode suffix of l. | %L0 | l | |
N | print maskz. | %N7 | {z} | {z} |
p | Print raw symbol name (without syntax-specific prefixes). | %p2 | 42 | 42 |
P | If used for a function, print the PLT suffix and generate PIC code.For example, emit foo@PLT instead of ’foo’ for the functionfoo(). If used for a constant, drop all syntax-specific prefixes andissue the bare constant. See p above. | |||
q | Print the DImode name of the register. | %q0 | %rax | rax |
Q | print the opcode suffix of q. | %Q0 | q | |
R | print embedded rounding and sae. | %R4 | {rn-sae}, | , {rn-sae} |
r | print only sae. | %r4 | {sae}, | , {sae} |
s | print a shift double count, followed by the assemblers argumentdelimiterprint the opcode suffix of s. | %s1 | $2, | 2, |
S | print the opcode suffix of s. | %S0 | s | |
t | print the V8SFmode name of the register. | %t5 | %ymm0 | ymm0 |
T | print the opcode suffix of t. | %T0 | t | |
V | print naked full integer register name without %. | %V0 | eax | eax |
w | Print the HImode name of the register. | %w0 | %ax | ax |
W | print the opcode suffix of w. | %W0 | w | |
x | print the V4SFmode name of the register. | %x5 | %xmm0 | xmm0 |
y | print 'st(0)' instead of 'st' as a register. | %y6 | %st(0) | st(0) |
z | Print the opcode suffix for the size of the current integer operand (one of b /w /l /q ). | %z0 | l | |
Z | Like z , with special suffixes for x87 instructions. |
6.47.2.9 x86 Floating-Point asm
Operands
On x86 targets, there are several rules on the usage of stack-like registersin the operands of an asm
. These rules apply only to the operandsthat are stack-like registers:
- Given a set of input registers that die in an
asm
, it isnecessary to know which are implicitly popped by theasm
, andwhich must be explicitly popped by GCC.An input register that is implicitly popped by the
asm
must beexplicitly clobbered, unless it is constrained to match anoutput operand. - For any input register that is implicitly popped by an
asm
, it isnecessary to know how to adjust the stack to compensate for the pop.If any non-popped input is closer to the top of the reg-stack thanthe implicitly popped register, it would not be possible to know what thestack looked like—it’s not clear how the rest of the stack “slidesup”.All implicitly popped input registers must be closer to the top ofthe reg-stack than any input that is not implicitly popped.
It is possible that if an input dies in an
asm
, the compiler mightuse the input register for an output reload. Consider this example:This code says that input
b
is not popped by theasm
, and thattheasm
pushes a result onto the reg-stack, i.e., the stack is onedeeper after theasm
than it was before. But, it is possible thatreload may think that it can use the same register for both the input andthe output.To prevent this from happening,if any input operand uses the ‘f’ constraint, all output registerconstraints must use the ‘&’ early-clobber modifier.
The example above is correctly written as:
- Some operands need to be in particular places on the stack. Alloutput operands fall in this category—GCC has no other way toknow which registers the outputs appear in unless you indicatethis in the constraints.
Output operands must specifically indicate which register an outputappears in after an
asm
. ‘=f’ is not allowed: the operandconstraints must select a class with a single register. - Output operands may not be “inserted” between existing stack registers.Since no 387 opcode uses a read/write operand, all output operandsare dead before the
asm
, and are pushed by theasm
.It makes no sense to push anywhere but the top of the reg-stack.Output operands must start at the top of the reg-stack: outputoperands may not “skip” a register.
- Some
asm
statements may need extra stack space for internalcalculations. This can be guaranteed by clobbering stack registersunrelated to the inputs and outputs.
This asm
takes one input, which is internally popped, and produces two outputs.
This asm
takes two inputs, which are popped by the fyl2xp1
opcode,and replaces them with one output. The st(1)
clobber is necessary for the compiler to know that fyl2xp1
pops both inputs.
6.47.2.10 MSP430 Operand Modifiers
The list below describes the supported modifiers and their effects for MSP430.
Modifier | Description |
---|---|
A | Select low 16-bits of the constant/register/memory operand. |
B | Select high 16-bits of the constant/register/memoryoperand. |
C | Select bits 32-47 of the constant/register/memory operand. |
D | Select bits 48-63 of the constant/register/memory operand. |
H | Equivalent to B (for backwards compatibility). |
I | Print the inverse (logical NOT ) of the constantvalue. |
J | Print an integer without a # prefix. |
L | Equivalent to A (for backwards compatibility). |
O | Offset of the current frame from the top of the stack. |
Q | Use the A instruction postfix. |
R | Inverse of condition code, for unsigned comparisons. |
W | Subtract 16 from the constant value. |
X | Use the X instruction postfix. |
Y | Subtract 4 from the constant value. |
Z | Subtract 1 from the constant value. |
b | Append .B , .W or .A to theinstruction, depending on the mode. |
d | Offset 1 byte of a memory reference or constant value. |
e | Offset 3 bytes of a memory reference or constant value. |
f | Offset 5 bytes of a memory reference or constant value. |
g | Offset 7 bytes of a memory reference or constant value. |
p | Print the value of 2, raised to the power of the givenconstant. Used to select the specified bit position. |
r | Inverse of condition code, for signed comparisons. |
x | Equivialent to X , but only for pointers. |
Next: Constraints, Previous: Basic Asm, Up: Using Assembly Language with C [Contents][Index]