Author Topic: Converting assembly to C  (Read 24615 times)

0 Members and 12 Guests are viewing this topic.

Offline metertech58761Topic starter

  • Frequent Contributor
  • **
  • Posts: 271
  • Country: us
Converting assembly to C
« on: March 26, 2025, 04:11:55 pm »
I have some assembly code I want to eventually rewrite into C, and I have isolated the four main loops (there's still an interrupt, but that comes later).

In these loops, there is some code where the operator is asked to press the Repeat key if they want to run the current test again or press the Next key to continue.

A typical instance:

Code: [Select]
suite3_11
        JSR   getKey
        CMPA  #$13 ; repeat
        BNE   suite3_12
        BRA   suite3 ; re-run current test

suite3_12
        CMPA  #$1B ; next
        BNE   suite3_11
; we now continue to the next step

So, how would I go about doing this?
 

Offline pqass

  • Super Contributor
  • ***
  • Posts: 1162
  • Country: ca
Re: Converting assembly to C
« Reply #1 on: March 26, 2025, 05:46:49 pm »
Given:
 JSR      = function call
 CMPA  = if ( accumulator == '\x13' ) ...
 BNE    = else
 BRA    = goto


Rewrite as:

Code: [Select]
suite3:
suite3_11:
  char ch = getKey();
  if ( ch == '\x13' ) goto suite3;
suite3_12:
  if ( ch != '\x1b' ) goto suite3_11;
  ...more next step code here...


But the above is too literal; make it more structured (less spaghetti) like:

Code: [Select]
void suite3() {
  while(1) {
    switch(getKey()) {
    case '\x13': continue;
    case '\x1b': break;
    ...more case code here...
    default: continue;
    }
    ...more next step code here...
    break;  // only once thru loop; used to avoid gotos.
  }
}

Your assembly is a bit odd because BRA suite3 and BNE suite3_11 jumps to the same point unless there is test suite3_10 code prior to suite3_11.  Maybe you intend to JSR getKey at the top of suite3 and then testing different keys results in exit, re-run, or different tests?  Seems odd to have JSR getKey be specific to the suite3_11 test.  Yes, this may seem more convoluted than the earlier code snip but you may see a theme develop and re-arrange further.
« Last Edit: March 26, 2025, 05:59:44 pm by pqass »
 

Offline metertech58761Topic starter

  • Frequent Contributor
  • **
  • Posts: 271
  • Country: us
Re: Converting assembly to C
« Reply #2 on: March 26, 2025, 06:07:42 pm »
Here's the abbreviated code I'm looking to eventually rewrite:

The existing code writes to a display buffer that gets pushed into a 8279 display controller via calls to the dispRefresh routine. I want to replace all that with writes to an LCD.

As for the snippet I just showed, there are multiple instances of this throughout the process loops.

Basically, after a test or group is completed, the keypad is polled for a keypress (poll the 8279's EIRQ line, wait for a state change, then retrieve the matrix value - that code would also be replaced).

The code shown is a loop that you can only exit if you press Repeat (sending you back to a designated point) or Next (falling down to the next instruction).

I plan to replace the matrix value with flags for each of the function keys (Clear, Next, Repeat, Test, Enter). There's a sixth function key (Reset), but I'm debating if I want a soft or hard reset.
« Last Edit: March 26, 2025, 06:11:07 pm by metertech58761 »
 

Offline pqass

  • Super Contributor
  • ***
  • Posts: 1162
  • Country: ca
Re: Converting assembly to C
« Reply #3 on: March 26, 2025, 08:16:17 pm »
The following code should re-implement everything from suite3 on down.  Please confirm as I've only compiled it; not tested.
It's not a simple pattern as there are some tests where repeat isn't from the first test or some tests jump to other tests without key checking.

I suggest you to print it out on paper and highlight the JSR getKey repeat key and next key check blocks.
Take note of which tests the repeat and next key-presses jump to.

Code: [Select]
int repeatFrom = 1;  // assume repeat from first test unless otherwise changed
for(int test = 1; test <= 8; ) {             // loop from first to last test
  switch(test) {
  case 1: test_61(); break;   // DCT Analog 1   this test is always run upon entry to the loop before key check
  case 2: test_62(); break;   // DCT Analog 2
  case 3: test_63(); break;   // DCT Analog 3
  case 4: test_64(); break;   // DCT Analog 4
  case 5: if (optbyte & 0x02) {
            test_70(); // download data from DCT
            test_71(); // send message to DCT
            test_72(); // strobe DCT relays
            repeatFrom = 5;
            test++; //skip over 6
          } else {
            test_75(); // get dctdata1 value from UUT
            test = 6;  // jump to specific test
            continue;  // don't test for keypress
          }
          break;
  case 6: test_76(); // DCT relay tests
          repeatFrom = 6;
          break;
  case 7: test_73(); // write data back to DCT (restore relay status?)
          test = 8;  // jump to specific test
          continue;  // don't test for keypress
  case 8: if (testSet != '\x01') {
            test_78(); // turn off DCT test mode
          }
          test_80(); // get / display toggle switch status
          break;
  }

  while (1) {
    char ch = getKey();
    if (ch == '\x13') test = repeatFrom; // REPEAT KEY PRESSED:    repeat from given test
    else if (ch == '\x1b') test++;       // NEXT KEY PRESSED:      do next test
    else continue;                       // ANY OTHER KEY PRESSED: do nothing but query for a key press
    break;                               // a key was pressed so we exit inner loop to do the test.
  }

  repeatFrom = 1;  // assume repeat from first test unless changed
}

EDIT: had to move test_76() to its own state.
« Last Edit: March 26, 2025, 11:17:23 pm by pqass »
 

Online kripton2035

  • Super Contributor
  • ***
  • Posts: 2897
  • Country: fr
    • kripton2035 schematics repository
Re: Converting assembly to C
« Reply #4 on: March 26, 2025, 08:17:55 pm »
Today's IA are very good for translating one programming language into another...
here is a quick and dirty try at converting your code into C.
you will need the real device to test it, so I can't do it !
 

Offline pqass

  • Super Contributor
  • ***
  • Posts: 1162
  • Country: ca
Re: Converting assembly to C
« Reply #5 on: March 26, 2025, 08:53:31 pm »
Today's IA are very good for translating one programming language into another...

To me, the assembly version is more readable.
 

Offline metertech58761Topic starter

  • Frequent Contributor
  • **
  • Posts: 271
  • Country: us
Re: Converting assembly to C
« Reply #6 on: March 27, 2025, 07:29:07 am »
It'll take a bit to digest that code.

I tried to transliterate the assembly instructions into C a while back and came up with some really clunky, ugly code.

When I instead started to group certain instructions together - i.e., from:

Code: [Select]
suite2
        LDAA  testSet
        CMPA  #$01
        BEQ   test15
        JMP   test20

to:

Code: [Select]
suite2:
        if (testSet == 1) { test15(); }
        else { test20(); }

things start to become easier to rewrite.

I just need some kind of 'do...while' or switch statement or something to handle those breakpoints where the operator can only press Repeat or Next to continue. :)

I eventually plan to use some kind of keyboard handler suited to whatever PIC or module I use, so instead of watching for matrix values, I would use flags like keyRepeat or keyNext respectively.
« Last Edit: March 27, 2025, 07:32:16 am by metertech58761 »
 

Offline Picuino

  • Super Contributor
  • ***
  • Posts: 1460
  • Country: es
    • Picuino
Re: Converting assembly to C
« Reply #7 on: March 27, 2025, 02:55:42 pm »
Code: [Select]
suite3_11
        JSR   getKey
        CMPA  #$13 ; repeat
        BNE   suite3_12
        BRA   suite3 ; re-run current test

suite3_12
        CMPA  #$1B ; next
        BNE   suite3_11
; we now continue to the next step

Gotos are very powerful in assembler, but in C it is the (small) functions that give you the power.
I would divide the tests into different functions, one for each test, and another function to ask the keyboard:

Code: (c) [Select]
#define True (1)
#define False (0)

int tests(void) {
   test_suite_1();
   test_suite_2();
   test_suite_3();
   test_suite_4();
}


int test_suite_3(void) {
    do {
        // Current Suite 3 test


    } while (kb_is_end() == False);
}


int kb_is_end() {
    while (True) {
        c = getchar();
        if (c == 0x13) return False;
        if (c == 0x1B) return True;
    };
}

« Last Edit: March 27, 2025, 03:10:37 pm by Picuino »
 

Offline metertech58761Topic starter

  • Frequent Contributor
  • **
  • Posts: 271
  • Country: us
Re: Converting assembly to C
« Reply #8 on: March 27, 2025, 05:17:15 pm »
That's my plan. The original assembly as dumped from the EPROMs was absolutely horrendous - like it was written by an intern with an Assembly Language 101 book at hand.

I have since massaged the assembly into a more logical and readable version, with the test steps themselves moved into subroutines (followed by the existing subroutines).
Just need to get past this bit of coder's block.

Edit: To illustrate - this is the transliteration I eventually worked out:

Code: [Select]
testStep:
test_call();

checkpoint:
getKey(keyNext,keyRepeat);
if (keyRepeat == true) { goto testStep; }
else if (keyNext != true) { goto checkpoint; }

Was there a more elegant approach?
« Last Edit: March 27, 2025, 05:33:54 pm by metertech58761 »
 

Offline pqass

  • Super Contributor
  • ***
  • Posts: 1162
  • Country: ca
Re: Converting assembly to C
« Reply #9 on: March 27, 2025, 06:42:49 pm »
Primitive types (boolean) as parameters are pass-by-value so they won't be updated by the function.
You'd have to pass an address to them, like:
Code: [Select]
getKey(&keyNext,&keyRepeat);
Instead of using a boolean for each key, why don't use a #define to check for the key that was pressed, like:
Code: [Select]
#define KEY_REPEAT 0x13
#define KEY_NEXT   0x1b


char ch;   // declare at top of block


testStep:
test_call();

while((ch = getKey()) != KEY_NEXT) {
  if (ch == KEY_REPEAT) goto testStep;
}
 
The following users thanked this post: metertech58761

Offline metertech58761Topic starter

  • Frequent Contributor
  • **
  • Posts: 271
  • Country: us
Re: Converting assembly to C
« Reply #10 on: March 27, 2025, 11:28:22 pm »
That 'while' statement is what I was thinking of, but wasn't sure how to format it properly.
I'll see how well I do in rewriting one of the test suites and post back once I've gone through it. Thanks!
 

Offline metertech58761Topic starter

  • Frequent Contributor
  • **
  • Posts: 271
  • Country: us
Re: Converting assembly to C
« Reply #11 on: March 27, 2025, 11:54:53 pm »
And it didn't take that long... here's my take on the DCT test group:

Code: [Select]
// Two-way unit tests: Distribution Control Terminal test suite

suite3:

test61(); // Read DCT Analog 1

while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite3; }

test62(); // Read DCT Analog 2

while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite3; }

test63(); // Read DCT Analog 3

while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite3; }

test64(); // Read DCT Analog 4

while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite3; }

if (optByte && 2 != 0) // this may be a flag for latched vs. timed relays
{

suite3_01:

test_70(); // download data from DCT

test_71(); // send message to DCT

test_72(); // strobe DCT relays

while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite3_01; }

test_73(); // write data back to DCT (restore relay status?)

}

else
{

test_75(); // get dctdata1 value from UUT

suite3_06:

test_76(); // DCT relay tests

while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite3_06; }

}

suite3_09:

if (testSet != 1) { test78(); } // turn off DCT test mode

test80(); // display toggle switch status

while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite3; }

// We're done. Back to main menu

keyMask = %01001000;
goto loopMain;

// End of DCT tests

And the LMT-1xx group:

Code: [Select]
// LMT-1xx test suite (receive-only)

suite1:

if (rlyNum != 0)
{

test35a(); // exercise timed relays A - D

while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite1; }

}

if (fctCtlNum != 0) { test40a(); } // exercise latched relay D

// We're done. Back to main menu

keyMask = %01001000;
goto loopMain;

// End of LMT-1xx tests

How does that look?
« Last Edit: March 28, 2025, 12:21:16 am by metertech58761 »
 

Offline pqass

  • Super Contributor
  • ***
  • Posts: 1162
  • Country: ca
Re: Converting assembly to C
« Reply #12 on: March 28, 2025, 12:54:58 am »
Looks good but I can do better by making the while getKey loop into a macro:

Code: [Select]
#define WAIT_ON_NEXT_OR_REPEAT(target)     while((ch = getKey()) != KEY_NEXT) { if (ch == KEY_REPEAT) goto target; }


suite3:

test61(); // Read DCT Analog 1

WAIT_ON_NEXT_OR_REPEAT(suite3);

test62(); // Read DCT Analog 2

WAIT_ON_NEXT_OR_REPEAT(suite3);

test63(); // Read DCT Analog 3

WAIT_ON_NEXT_OR_REPEAT(suite3);

test64(); // Read DCT Analog 4

WAIT_ON_NEXT_OR_REPEAT(suite3);

if (optByte && 2 != 0) // this may be a flag for latched vs. timed relays
{

suite3_01:

test_70(); // download data from DCT

test_71(); // send message to DCT

test_72(); // strobe DCT relays

WAIT_ON_NEXT_OR_REPEAT(suite3_01);

test_73(); // write data back to DCT (restore relay status?)

}

else
{

test_75(); // get dctdata1 value from UUT

suite3_06:

test_76(); // DCT relay tests

WAIT_ON_NEXT_OR_REPEAT(suite3_06);

}

suite3_09:

if (testSet != 1) { test78(); } // turn off DCT test mode

test80(); // display toggle switch status

WAIT_ON_NEXT_OR_REPEAT(suite3);

// We're done. Back to main menu

keyMask = 0b01001000;
goto loopMain;

// End of DCT tests

Changed "keyMask = %01001000;" to "keyMask = 0b01001000;"


Or,
to minimize the generated code at every key check, you can call a function containing the key check loop instead.
Code: [Select]
int wasRepeatKeyPressed() {
char ch;
while((ch = getKey()) != KEY_NEXT) {
if (ch == KEY_REPEAT) return 1;
}
return 0;
}

#define WAIT_ON_NEXT_OR_REPEAT(target)     if (wasRepeatKeyPressed()) goto target

« Last Edit: March 28, 2025, 06:24:45 am by pqass »
 
The following users thanked this post: metertech58761

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 5733
  • Country: Earth
Re: Converting assembly to C
« Reply #13 on: March 28, 2025, 01:25:24 am »
So, how would I go about doing this?

Code: [Select]
int suiteId = 3;                // start with suite3
for (;;) {
   
    // Call suite
    switch (suiteId) {
        case 3: suite3(); break;
        case 4: suite4(); break;
        default:                // unknown suite - do nothing
            break;         
    }
   
    // Check keyboard input
    int nextSuiteId = -1;       // set next suite undefined
    while (nextSuiteId < 0) {
        switch (getKey()) {
            case 0x13:          // repeat suite
                nextSuiteId = suiteId;
                break;
            case 0x1b:          // next suite
                nextSuiteId = suiteId + 1;
                break;
            default:            // unknown key - do nothing
                break;
        }
    }
    suiteId = nextSuiteId;
}
« Last Edit: March 28, 2025, 01:41:26 am by radiolistener »
 

Offline metertech58761Topic starter

  • Frequent Contributor
  • **
  • Posts: 271
  • Country: us
Re: Converting assembly to C
« Reply #14 on: March 28, 2025, 07:33:23 am »
pqass: I'm really liking the idea of a macro, and I know there WILL be opportunities to add more as the program evolves.

But I see I need to do two things before I keep going:

One, I need to revisit the structure of the suite2 loops. I may need to tear the assembly down and rebuild from scratch, splitting it based on uutType = 2 and uutType = 4 (the third case, uutType = 1, is suite1). Like I said, the original assembly before I tided it up was horrendous.

The other is to find a C library I'd seen a while back for writing to a 4x20 LCD, as I will need to start laying out the display and building the corresponding macros for that as well.
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 5733
  • Country: Earth
Re: Converting assembly to C
« Reply #15 on: March 28, 2025, 10:13:44 am »
See the code example above.

Regarding macros in C, it's generally advisable to avoid using them to prevent potential issues. Macros can make code harder to read and maintain, and they often introduce hidden errors that are difficult to detect and debug. Whenever possible, consider using const, inline functions, or enum for better type safety and code clarity.

For example:
Code: [Select]
#include <stdio.h>

#define true false

int main() {
    if (true) {
        printf("This should print, but it doesn't.\n");
    } else {
        printf("This should never print, but it does.\n");
    }
    return 0;
}

In this example, you typically don't see that true is redefined as false by a macro because this definition is hidden somewhere in a header file. At first glance, the code in the main() function looks correct but behaves differently from what you expect.

In addition, using macros limits the compiler's ability to perform type checking, which often leads to hidden errors that are difficult to detect.

The only genuinely useful feature of macros in C is conditional compilation using #ifdef. It allows you to include or exclude parts of the code based on specific conditions, which can be helpful for cross-platform compatibility, debugging, or configuring different build options. In all other cases, avoid using macros to reduce the number of potential problems in your code.

Historically, many header files were written at a time when the C language did not support constants and enums. As a result, macros were heavily used to define constants and other values. Unfortunately, this legacy remains, and in practice, you will often encounter macros in existing codebases. It is a historical artifact that developers must contend with, but whenever possible, it is better to use modern, type-safe alternatives such as const, enum, or inline functions.
« Last Edit: March 28, 2025, 10:35:36 am by radiolistener »
 

Offline pqass

  • Super Contributor
  • ***
  • Posts: 1162
  • Country: ca
Re: Converting assembly to C
« Reply #16 on: March 28, 2025, 01:28:22 pm »
No doubt, macros can get ugly.  Keep it simple.
I'm using them to help improve readability in my reply#12 by removing the visual noise and minimizing the use of labels.
The state machine in reply#3 is more compact but is harder to read compared to your linear flow in reply#12.

Quote
...find a C library...for writing to a 4x20 LCD

See my minimalist one here.  Just adjust the lcdSend() function to send to a SPI (74HC595) attached or 4-bit parallel attached LCD.
For a LCD refresher video and HD44780 datasheet see here.
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 5733
  • Country: Earth
Re: Converting assembly to C
« Reply #17 on: March 28, 2025, 06:35:09 pm »
I'm using them to help improve readability in my reply#12 by removing the visual noise and minimizing the use of labels.

Avoid using macros and goto statements in C code, as their presence is considered as a sign of extremely poor code quality (also called "shitty code" or "spaghetti code").

You don't need macros or goto statements to make your code more readable or easier to debug. In fact, they tend to do the opposite - making the code harder to understand and introducing potential bugs that can be difficult to track down. Instead, focus on writing clean, structured code with clear control flow and type-safe constructs.

If you feel the need to use a macro or goto statement in your code, it's a strong indication that something is fundamentally wrong with your approach.

For example, the projects I have worked on contained gigabytes (if not terabytes) of source code in various languages, and none of them included even a single goto statement.
« Last Edit: March 28, 2025, 06:48:32 pm by radiolistener »
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 11159
  • Country: fi
Re: Converting assembly to C
« Reply #18 on: March 28, 2025, 07:07:35 pm »
As always, ignore radiolisterer. Macros are very much present in every non-trivial real world high-quality project for very good reasons; they are one of the fundamental reasons why C still is a popular language. Used right, they make the difference between unmaintainable copy-pasta spaghetti mess, and a readable/maintainable project.

The name of the relevant concept is Don't Repeat Yourself.

And then again, any feature can be abused.

But I'm sure radiolistener is happy copy-pasting code or using ChatGPT to generate it. Such write-only code indeed does not need to use macros.

Goto is an excellent tool for people management. Once you hear stuff like... "goto is considered bad practice which leads to spaghetti code"... you instantly know that this person is operating like a bot with very little neuron activation in brain. They are beyond salvage and considered harmful, and thusly ignored; then, the project can go on, using goto for the usual purposes like exiting an outer loop (when language lacks labelled loop bodies), or error management (when language lacks try-catch exceptions).
« Last Edit: March 28, 2025, 07:13:19 pm by Siwastaja »
 
The following users thanked this post: guenthert, SiliconWizard

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 5733
  • Country: Earth
Re: Converting assembly to C
« Reply #19 on: March 28, 2025, 08:13:05 pm »
As always, ignore radiolisterer.

Let's keep the discussion respectful and focused on technical arguments rather than insulting personalities. It's perfectly fine to disagree, but dismissing someone's input by telling others to ignore them adds no value to the conversation.

It's more productive to debate the merits of different approaches based on facts and best practices rather than suggesting whose opinions should or shouldn't be heard. Let’s keep the conversation constructive.


So please refrain from resorting to cheap trolling and personal attacks by shifting the discussion towards personalities rather than the technical subject at hand

Macros are very much present in every non-trivial real world high-quality project for very good reasons; they are one of the fundamental reasons why C still is a popular language. Used right, they make the difference between unmaintainable copy-pasta spaghetti mess, and a readable/maintainable project.

The name of the relevant concept is Don't Repeat Yourself.

While it's true that macros are still commonly found in modern projects, they are largely a relic from older versions of C compilers, where the language syntax was less developed, and features like enum, constants, and inline functions weren't available. As a result, macros were used to achieve similar functionality.

Refactoring old legacy code is often a complex and time-consuming task that typically doesn't provide significant benefits, which is why such code is often left as is. However, it is important to acknowledge that macros come with well-documented downsides, including reduced readability, lack of type checking, and an increased potential for hidden bugs.

Many high-quality, modern projects actively avoid macros in favor of safer and more maintainable alternatives, such as const, inline functions, and enum. These alternatives not only improve the readability and safety of the code but also support better maintainability in the long term.

In other words, the old code using macros has already been debugged and is functioning as expected. While refactoring it to modern syntax will result in more readable and safer code, and you may uncover and fix some issues in the process, it will require a significant investment of time in development and debugging to achieve a version of the code that ultimately behaves in much the same way as the original. As a result, such legacy code is often left as-is. Additionally, macros may sometimes be used in new code to maintain consistency within the project, but this does not imply that it is the best or most appropriate approach for writing readable and safe code.

Goto is an excellent tool for people management. Once you hear stuff like... "goto is considered bad practice which leads to spaghetti code"... you instantly know that this person is operating like a bot

It’s important to separate technical practices from personal opinions. When someone says, "goto is considered bad practice and leads to spaghetti code," it typically means they understand the issues that come with using goto - such as creating hard-to-follow control flow and making debugging more difficult. Recognizing these problems is a sign of someone being aware of best practices and trying to avoid common pitfalls.

I worked in the highly regulated medical device industry, where the quality of code is critically important. This is because the code we wrote directly impacted human lives - it was responsible for the success of heart surgeries and other critical procedures. In such an environment, every line of code had to be meticulously reviewed and tested to ensure reliability and safety, as any failure could have severe consequences.

If you’ve had heart surgery at one of the leading hospitals in the United States, Israel, or Europe, it’s quite likely that my code was involved in the procedure. The software I developed played a critical role in ensuring the success of such complex and life-saving operations.

Engineers working on such projects understand the risks that come with poorly structured code. In fact, goto is often avoided precisely because it can introduce maintainability and reliability issues. In our company, the use of goto in code reviews or interviews would have been a major red flag, and anyone who demonstrated a reliance on it would not have passed the interview.

I understand that not all projects require such strict coding practices, and in my personal hobby projects, I sometimes take a more relaxed approach, but I never use goto statement even in my hobby projects and don't see any reason to use it. So, while goto might be considered acceptable in some niche cases, in general, it’s better to follow practices that enhance readability, maintainability, and safety - which is why goto is discouraged in modern development.
« Last Edit: March 28, 2025, 08:20:05 pm by radiolistener »
 
The following users thanked this post: nctnico

Offline Picuino

  • Super Contributor
  • ***
  • Posts: 1460
  • Country: es
    • Picuino
Re: Converting assembly to C
« Reply #20 on: March 28, 2025, 08:19:17 pm »
Gotos can be useful in C, but only for particular purposes described.
Assembly uses a lot of gotos, that you should not use in C.
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 5733
  • Country: Earth
Re: Converting assembly to C
« Reply #21 on: March 28, 2025, 08:45:03 pm »
Interestingly, while reviewing the code of a hobby project (disassembler) I wrote 30 years ago, I discovered a goto statement in one of the algorithms. :)

What’s even more interesting is that I vividly remember the moment when I wrote this code - at the time, I simply couldn't find a better solution, even though I was already aware of the drawbacks of using goto. Now, with more experience, I was able to easily refactor the code to make it more readable, without relying on goto. This highlights that the desire to use goto is not due to its utility, but rather a lack of experience and knowledge, when a developer hasn’t yet encountered better approaches to writing code and hasn’t found a more effective solution.

Now, I don't see any reason to use goto at all. And it's important to note - not because it's considered bad practice, not for religious reasons, and not because any particular group of people or company believes it's wrong, but simply because I don't see any practical situations where goto would be beneficial, especially since I know more effective solutions that can be implemented without it.

 

Offline metertech58761Topic starter

  • Frequent Contributor
  • **
  • Posts: 271
  • Country: us
Re: Converting assembly to C
« Reply #22 on: March 29, 2025, 09:10:33 pm »
Here's the rewrite after some structural work to get the three two-way suites into one.

I can't see how to minimize the goto statements - most are attached to conditionals, the only 'hard' goto statements are returning to the main loop or to the error handler.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17774
  • Country: fr
Re: Converting assembly to C
« Reply #23 on: March 29, 2025, 11:16:14 pm »
Now, I don't see any reason to use goto at all. And it's important to note - not because it's considered bad practice, not for religious reasons, and not because any particular group of people or company believes it's wrong, but simply because I don't see any practical situations where goto would be beneficial, especially since I know more effective solutions that can be implemented without it.

That's an ultra-common topic as it seems and comes back on a regular basis.
You'll find the usual, "goto's are bad" and "those who say goto's are bad are just ignorant wankers with no practical experience".

I'm not sure either are very useful, but hey. There's little as polarizing as programming topics. And politics.

I often like to start with the obvious, that is the rationale of the original paper it originates from, which was just trying to convince people of the benefits of structured programming, which was absolutely not a given at the time. These days, nobody reaosnable would even question "structured programming", so that context is almost entirely lost.

The second point is that, apart from assembly with "branches", most uses of "goto" are in C and C++ when it's a convenient and efficient way of breaking out of some nested loops, or for error handling, where you have a function with many possible paths of error and a single point to go to to handle the error before returning. That's mostly for lack of better constructs, not at all because goto is cute, even less so an elegant way of dealing with program flow. But it works given the limitations of those languages.

Some other languages have proper ways of dealing with the same, like named loops (which are coming with C23 if I'm not mistaken?) and 'defer' constructs. I don't think anyone sane would prefer using "goto" rather than those two alternatives, but of course, YMMV.

Now even in C, there are ways you can often avoid goto for typical error handling, which I tend to prefer these days, although that's relatively recent. Instead of using goto, I'll wrap code that can produce errors in "do {...} while (false)" constructs, which I just 'break' out of after setting an error value, in case of error. The error value is tested after this "loop", and that often looks cleaner. Additional benefit is you can ultra easily turn this construct into "retry" construct by changing changing the do...while to a for with a certain number of iterations.

For breaking out of nested loops, unfortunately, I have no magic trick (until we get named loops). One common way of avoiding 'goto' in this case is to use flags, but that often looks clunky and is possibly less efficient, depending on the order in which you place the flag test in the loop conditions. Occasionally, it can make things more readable, as it shows the complete condition of a loop in only one place, but most often, it's just clunky.
 
The following users thanked this post: nctnico

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 5733
  • Country: Earth
Re: Converting assembly to C
« Reply #24 on: March 30, 2025, 08:22:53 am »
Here's the rewrite after some structural work to get the three two-way suites into one.

I can't see how to minimize the goto statements - most are attached to conditionals, the only 'hard' goto statements are returning to the main loop or to the error handler.

Just remove all labels from your code. Use functions instead. That's pretty easy, just write:
Code: [Select]
void suite2(int testSet) {
    if (testSet == 1) {
        test15(); // download address to UUT
    }
...
}

instead of
Code: [Select]
suite2:
...

The issue with your code is that you create spaghetti code by using multiple labels and jumping back and forth between different parts of the program. These jumps are unnecessary - you simply need to structure the execution flow sequentially without this mix of jumps. I recommend removing all goto statements and labels and rewriting the code in a more structured and readable manner.

Here is example on how to do it: https://www.eevblog.com/forum/programming/converting-assembly-to-c/msg5863129/#msg5863129

Simply forget about the goto statement entirely and write code as if the compiler doesn’t support it at all. Before long, you’ll notice how much easier it becomes to write and read your code. ;)

If you're struggling to implement a feature and feel the urge to use goto, just stop and forget about it. Instead, take a step back and think about how to achieve the same result without goto - it’s actually much easier than it seems. If you’re stuck, it likely means you’ve fixated on goto as the solution and need a way out of that mindset. Feel free to share what you're trying to accomplish here, and we’ll help you find a better approach.

Just remember, C code should not contain even a single goto.
« Last Edit: March 30, 2025, 09:10:52 am by radiolistener »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf