Home » U++ TheIDE » U++ TheIDE: Compiling, Linking, Debugging of your packages » How to link assembler compiled file
How to link assembler compiled file [message #61685] |
Sun, 18 May 2025 11:51  |
frederik.dumarey
Messages: 30 Registered: December 2021 Location: Belgium
|
Member |
|
|
Hello,
I added a assembler file named my_strlen.S to my package, the contents of this file are below:
.global _my_strlen # Export the symbol _my_strlen
.text # code section
_my_strlen:
#function prologue
pushq %rbp
movq %rsp, %rbp
movq %rdi, %rsi # copy the string pointer to %rsi
xorq %rax, %rax # zero %rax to use as a counter
strlen_loop:
cmpb $0, (%rsi) # compare byte at %rsi with 0 (null terminator)
je strlen_end # if zero, end of string reached
incq %rax # increment counter
incq %rsi # move to next character
jmp strlen_loop # repeat loop
strlen_end:
#function epilogue
popq %rbp
ret
Since this is AT&T assembler code, it compiled without any problem to a object file using right_click, build and compile option in TheIDE GUI. So far so good.
I then added a C++ file, which has the following content:
#include <iostream>
//declare the assembler function
extern "C" size_t my_strlen(const char* str);
int main(int argc, const char *argv[])
{
const char* message = "Hello from Assembler";
size_t length = my_strlen(message);
std::cout << "Message: " << message << std::endl;
std::cout << "Length: " << length << std::endl;
return 0;
}
which can also be compiled using the same method as stated before.
Now my question: how do I link those two object files in the GUI? I suppose I have to go to Project menu item, then Custom build steps, but what do I enter in all these fields?
Thanks.
Regards,
Frederik Dumarey
Belgium
|
|
|
Re: How to link assembler compiled file [message #61686 is a reply to message #61685] |
Thu, 22 May 2025 09:59   |
 |
mirek
Messages: 14261 Registered: November 2005
|
Ultimate Member |
|
|
frederik.dumarey wrote on Sun, 18 May 2025 11:51Hello,
I added a assembler file named my_strlen.S to my package, the contents of this file are below:
.global _my_strlen # Export the symbol _my_strlen
.text # code section
_my_strlen:
#function prologue
pushq %rbp
movq %rsp, %rbp
movq %rdi, %rsi # copy the string pointer to %rsi
xorq %rax, %rax # zero %rax to use as a counter
strlen_loop:
cmpb $0, (%rsi) # compare byte at %rsi with 0 (null terminator)
je strlen_end # if zero, end of string reached
incq %rax # increment counter
incq %rsi # move to next character
jmp strlen_loop # repeat loop
strlen_end:
#function epilogue
popq %rbp
ret
Since this is AT&T assembler code, it compiled without any problem to a object file using right_click, build and compile option in TheIDE GUI. So far so good.
I then added a C++ file, which has the following content:
#include <iostream>
//declare the assembler function
extern "C" size_t my_strlen(const char* str);
int main(int argc, const char *argv[])
{
const char* message = "Hello from Assembler";
size_t length = my_strlen(message);
std::cout << "Message: " << message << std::endl;
std::cout << "Length: " << length << std::endl;
return 0;
}
which can also be compiled using the same method as stated before.
Now my question: how do I link those two object files in the GUI? I suppose I have to go to Project menu item, then Custom build steps, but what do I enter in all these fields?
Thanks.
Well, this is very exotic issue so it made me check the code and interestingly gcc builder (used with clang) simply treats .s files just like any other source (.c, .mm), including adding the .o to the linker. To be sure, you can check commandlines with Verbose.
|
|
|
Re: How to link assembler compiled file [message #61687 is a reply to message #61686] |
Sat, 24 May 2025 12:07   |
frederik.dumarey
Messages: 30 Registered: December 2021 Location: Belgium
|
Member |
|
|
Hello Mirek,
Thanks for mentioning the verbose console check. The .S and .CPP files were correctly compiled in .O files, but the linking failed on the global export. Most stupid error: i forgot the underscore for my variable .
#include <iostream>
//declare the assembler function
extern "C" size_t _my_strlen(const char* str);
int main(int argc, const char *argv[])
{
const char* message = "Hello from Assembler";
size_t length = _my_strlen(message);
std::cout << "Message: " << message << std::endl;
std::cout << "Length: " << length << std::endl;
return 0;
}
When you compile this all links up fine and runs perfectly!
So for those of you that want to include native assembler functions for SS2, AVX SIMD instructions, you can give it a try with this method
As Mirek mentioned, bit exotic, but I thought why not...
Have a nice day all of you,
Regards,
Frederik Dumarey
Belgium
|
|
|
Re: How to link assembler compiled file [message #61688 is a reply to message #61687] |
Sat, 24 May 2025 13:55   |
 |
mirek
Messages: 14261 Registered: November 2005
|
Ultimate Member |
|
|
frederik.dumarey wrote on Sat, 24 May 2025 12:07Hello Mirek,
Thanks for mentioning the verbose console check. The .S and .CPP files were correctly compiled in .O files, but the linking failed on the global export. Most stupid error: i forgot the underscore for my variable .
#include <iostream>
//declare the assembler function
extern "C" size_t _my_strlen(const char* str);
int main(int argc, const char *argv[])
{
const char* message = "Hello from Assembler";
size_t length = _my_strlen(message);
std::cout << "Message: " << message << std::endl;
std::cout << "Length: " << length << std::endl;
return 0;
}
When you compile this all links up fine and runs perfectly!
So for those of you that want to include native assembler functions for SS2, AVX SIMD instructions, you can give it a try with this method
As Mirek mentioned, bit exotic, but I thought why not...
Just to be sure, are you aware there are intrinsics for these?
(And also that we have common NEON/SSE2 subset supported?)
Mirek
|
|
|
Re: How to link assembler compiled file [message #61689 is a reply to message #61688] |
Sat, 24 May 2025 20:12  |
frederik.dumarey
Messages: 30 Registered: December 2021 Location: Belgium
|
Member |
|
|
Quote:
Just to be sure, are you aware there are intrinsics for these?
Yes, I do, and for those interested, I have a small example of it here:
#include <iostream>
#include <immintrin.h>
int main(int argc, const char *argv[])
{
alignas(32) float a[8] = {1.0f, 2.0f, 3.0f, 4.0f, 1.5f, 2.5f, 3.5f, 4.5f};
alignas(32) float b[8] = {5.0f, 6.0f, 7.0f, 8.0f, 5.5f, 6.5f, 7.5f, 8.5f};
//load data in AVX registers
__m256 vec_a = _mm256_load_ps(a);
__m256 vec_b = _mm256_load_ps(b);
//multiply elements
__m256 vec_mul = _mm256_mul_ps(vec_a, vec_b);
//horizontal add to compute the sum of all elements
__m256 temp = _mm256_hadd_ps(vec_mul, vec_mul);
temp = _mm256_hadd_ps(temp, temp);
//extract 128 lower bits and sum
__m128 low = _mm256_castps256_ps128 (temp);
__m128 high = _mm256_extractf128_ps (temp,1);
__m128 sum = _mm_add_ps (low, high);
//extract the final result
float result = _mm_cvtss_f32 (sum);
std::cout << "Dot product: " << result << std::endl;
return 0;
}
Regards,
Frederik Dumarey
Belgium
|
|
|
Goto Forum:
Current Time: Mon Jun 09 14:14:54 CEST 2025
Total time taken to generate the page: 0.05496 seconds
|